elastic_record 4.0.0 → 4.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -6
- data/Gemfile +0 -2
- data/README.md +25 -9
- data/elastic_record.gemspec +1 -1
- data/lib/elastic_record/as_document.rb +41 -0
- data/lib/elastic_record/callbacks.rb +11 -56
- data/lib/elastic_record/connection.rb +1 -1
- data/lib/elastic_record/doctype.rb +43 -0
- data/lib/elastic_record/index/deferred.rb +13 -15
- data/lib/elastic_record/index/documents.rb +23 -13
- data/lib/elastic_record/index/manage.rb +4 -6
- data/lib/elastic_record/index/mapping.rb +7 -26
- data/lib/elastic_record/index/settings.rb +17 -2
- data/lib/elastic_record/index.rb +12 -24
- data/lib/elastic_record/model.rb +14 -4
- data/lib/elastic_record/percolator_model.rb +44 -0
- data/lib/elastic_record/relation.rb +1 -2
- data/lib/elastic_record/searching.rb +5 -1
- data/lib/elastic_record/tasks/index.rake +0 -10
- data/lib/elastic_record.rb +3 -0
- data/test/dummy/app/models/mock_model.rb +108 -0
- data/test/dummy/app/models/project.rb +1 -1
- data/test/dummy/app/models/test_model.rb +1 -102
- data/test/dummy/app/models/test_percolator_model.rb +8 -0
- data/test/dummy/app/models/widget.rb +2 -5
- data/test/dummy/app/models/widget_query.rb +14 -0
- data/test/dummy/config/environments/test.rb +3 -3
- data/test/dummy/config/initializers/elastic_record.rb +1 -1
- data/test/elastic_record/as_document_test.rb +65 -0
- data/test/elastic_record/callbacks_test.rb +6 -81
- data/test/elastic_record/config_test.rb +1 -1
- data/test/elastic_record/doctype_test.rb +45 -0
- data/test/elastic_record/index/documents_test.rb +1 -1
- data/test/elastic_record/index/mapping_test.rb +16 -13
- data/test/elastic_record/index/settings_test.rb +34 -1
- data/test/elastic_record/index_test.rb +7 -15
- data/test/elastic_record/model_test.rb +1 -7
- data/test/elastic_record/percolator_model_test.rb +54 -0
- data/test/elastic_record/relation/batches_test.rb +0 -1
- data/test/elastic_record/relation/delegation_test.rb +0 -1
- data/test/elastic_record/relation/finder_methods_test.rb +0 -1
- data/test/elastic_record/relation_test.rb +0 -2
- data/test/elastic_record/searching_test.rb +7 -0
- metadata +11 -10
- data/lib/elastic_record/index/configurator.rb +0 -18
- data/lib/elastic_record/index/percolator.rb +0 -50
- data/lib/elastic_record/index/warmer.rb +0 -24
- data/lib/elastic_record/relation/admin.rb +0 -13
- data/test/elastic_record/index/configurator_test.rb +0 -18
- data/test/elastic_record/index/percolator_test.rb +0 -45
- data/test/elastic_record/index/warmer_test.rb +0 -20
- data/test/elastic_record/relation/admin_test.rb +0 -28
@@ -2,108 +2,7 @@ module TestModel
|
|
2
2
|
extend ActiveSupport::Concern
|
3
3
|
|
4
4
|
included do
|
5
|
-
|
6
|
-
extend ActiveModel::Callbacks
|
7
|
-
define_model_callbacks :save, :update, :create, :destroy
|
8
|
-
|
9
|
-
include ActiveModel::Dirty
|
10
|
-
include ActiveModel::Validations
|
11
|
-
|
5
|
+
include MockModel
|
12
6
|
include ElasticRecord::Model
|
13
7
|
end
|
14
|
-
|
15
|
-
module ClassMethods
|
16
|
-
def find(ids)
|
17
|
-
ids.map { |id| new(id: id) }
|
18
|
-
end
|
19
|
-
|
20
|
-
def where(query)
|
21
|
-
find query[:id]
|
22
|
-
end
|
23
|
-
|
24
|
-
def primary_key
|
25
|
-
'id'
|
26
|
-
end
|
27
|
-
|
28
|
-
def base_class
|
29
|
-
self
|
30
|
-
end
|
31
|
-
|
32
|
-
def create(attributes = {})
|
33
|
-
record = new(attributes)
|
34
|
-
record.save
|
35
|
-
record
|
36
|
-
end
|
37
|
-
|
38
|
-
def define_attributes(attributes)
|
39
|
-
define_attribute_methods attributes
|
40
|
-
|
41
|
-
attributes.each do |attribute|
|
42
|
-
define_method attribute do
|
43
|
-
instance_variable_get("@#{attribute}")
|
44
|
-
end
|
45
|
-
|
46
|
-
define_method "#{attribute}=" do |value|
|
47
|
-
send("#{attribute}_will_change!")
|
48
|
-
instance_variable_set("@#{attribute}", value)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
define_method 'attributes' do
|
53
|
-
Hash[attributes.map { |attr| [attr.to_s, send(attr)] }]
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def initialize(attrs = {})
|
59
|
-
self.attributes = attrs
|
60
|
-
end
|
61
|
-
|
62
|
-
def attributes=(attrs)
|
63
|
-
attrs.each do |key, val|
|
64
|
-
send("#{key}=", val)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def id=(value)
|
69
|
-
@id = value
|
70
|
-
end
|
71
|
-
|
72
|
-
def id
|
73
|
-
@id ||= rand(10000).to_s
|
74
|
-
end
|
75
|
-
|
76
|
-
def save
|
77
|
-
@persisted = true
|
78
|
-
callback_method = new_record? ? :create : :update
|
79
|
-
run_callbacks callback_method
|
80
|
-
end
|
81
|
-
|
82
|
-
def destroy
|
83
|
-
@destroyed = true
|
84
|
-
run_callbacks :destroy
|
85
|
-
end
|
86
|
-
|
87
|
-
def ==(other)
|
88
|
-
id == other.id
|
89
|
-
end
|
90
|
-
|
91
|
-
def changed?
|
92
|
-
true
|
93
|
-
end
|
94
|
-
|
95
|
-
def new_record?
|
96
|
-
!@persisted
|
97
|
-
end
|
98
|
-
|
99
|
-
def persisted?
|
100
|
-
@persisted
|
101
|
-
end
|
102
|
-
|
103
|
-
def destroyed?
|
104
|
-
@destroyed
|
105
|
-
end
|
106
|
-
|
107
|
-
def reload
|
108
|
-
end
|
109
8
|
end
|
@@ -5,13 +5,10 @@ class Widget
|
|
5
5
|
|
6
6
|
define_attributes [:name, :color, :warehouse_id]
|
7
7
|
|
8
|
-
self.
|
9
|
-
|
10
|
-
self.elastic_index.mapping[:properties].update(
|
8
|
+
self.doctype.mapping[:properties].update(
|
11
9
|
'name' => {
|
12
|
-
type: 'string',
|
10
|
+
type: 'string', index: 'not_analyzed',
|
13
11
|
fields: {
|
14
|
-
name: {type: 'string', index: 'not_analyzed'},
|
15
12
|
analyzed: {type: 'string', index: 'analyzed'}
|
16
13
|
}
|
17
14
|
},
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class WidgetQuery
|
2
|
+
include TestPercolatorModel
|
3
|
+
|
4
|
+
define_attributes [:name, :color]
|
5
|
+
|
6
|
+
self.percolates_model = Widget
|
7
|
+
|
8
|
+
def as_search_document
|
9
|
+
filters = {}
|
10
|
+
filters[:name] = name if name
|
11
|
+
filters[:color] = color if color
|
12
|
+
percolates_model.elastic_search.filter(filters).as_elastic
|
13
|
+
end
|
14
|
+
end
|
@@ -12,9 +12,9 @@ Rails.application.configure do
|
|
12
12
|
# preloads Rails for running tests, you may have to set it to true.
|
13
13
|
config.eager_load = false
|
14
14
|
|
15
|
-
# Configure
|
16
|
-
config.
|
17
|
-
config.
|
15
|
+
# Configure public file server for tests with Cache-Control for performance.
|
16
|
+
config.public_file_server.enabled = true
|
17
|
+
config.public_file_server.headers = { 'Cache-Control' => 'public, max-age=3600' }
|
18
18
|
|
19
19
|
# Show full error reports and disable caching.
|
20
20
|
config.consider_all_requests_local = true
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class ElasticRecord::AsDocumentTest < MiniTest::Test
|
4
|
+
def test_as_search_document
|
5
|
+
Widget.new(id: '10', color: 'green').tap do |widget|
|
6
|
+
assert_equal({"color" => "green"}, widget.as_search_document)
|
7
|
+
end
|
8
|
+
|
9
|
+
Widget.new(id: '10', color: '').tap do |widget|
|
10
|
+
assert_equal({}, widget.as_search_document)
|
11
|
+
end
|
12
|
+
|
13
|
+
Widget.new(id: '10', color: false).tap do |widget|
|
14
|
+
assert_equal({"color" => false}, widget.as_search_document)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_as_dirty_search
|
19
|
+
Widget.new(id: '10', color: 'green').tap do |widget|
|
20
|
+
assert_equal({'color' => 'green'}, widget.as_partial_update_document)
|
21
|
+
end
|
22
|
+
|
23
|
+
Widget.new(id: '10').tap do |widget|
|
24
|
+
assert_equal({}, widget.as_partial_update_document)
|
25
|
+
end
|
26
|
+
|
27
|
+
Widget.new(id: '10', color: '').tap do |widget|
|
28
|
+
assert_equal({'color' => nil}, widget.as_partial_update_document)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class SpecialFieldsModel
|
33
|
+
include TestModel
|
34
|
+
|
35
|
+
class Author
|
36
|
+
def as_search_document
|
37
|
+
{name: 'Jonny'}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
self.doctype.mapping[:properties].update(
|
42
|
+
author: {
|
43
|
+
type: :object
|
44
|
+
},
|
45
|
+
commenters: {
|
46
|
+
type: :nested
|
47
|
+
}
|
48
|
+
)
|
49
|
+
|
50
|
+
def author
|
51
|
+
Author.new
|
52
|
+
end
|
53
|
+
|
54
|
+
def commenters
|
55
|
+
[Author.new, Author.new]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_as_search_document_with_special_fields
|
60
|
+
doc = SpecialFieldsModel.new.as_search_document
|
61
|
+
|
62
|
+
assert_equal({name: 'Jonny'}, doc[:author])
|
63
|
+
assert_equal([{name: 'Jonny'}, {name: 'Jonny'}], doc[:commenters])
|
64
|
+
end
|
65
|
+
end
|
@@ -21,7 +21,7 @@ class ElasticRecord::CallbacksTest < MiniTest::Test
|
|
21
21
|
|
22
22
|
def test_deleted_from_index
|
23
23
|
widget = Widget.new id: '10', color: 'green'
|
24
|
-
Widget.elastic_index.index_document(widget.id, widget.
|
24
|
+
Widget.elastic_index.index_document(widget.id, widget.as_search_document)
|
25
25
|
|
26
26
|
assert Widget.elastic_index.record_exists?(widget.id)
|
27
27
|
|
@@ -30,95 +30,20 @@ class ElasticRecord::CallbacksTest < MiniTest::Test
|
|
30
30
|
refute Widget.elastic_index.record_exists?(widget.id)
|
31
31
|
end
|
32
32
|
|
33
|
-
def test_as_search
|
34
|
-
Widget.new(id: '10', color: 'green').tap do |widget|
|
35
|
-
assert_equal({"color" => "green"}, widget.as_search)
|
36
|
-
end
|
37
|
-
|
38
|
-
Widget.new(id: '10', color: '').tap do |widget|
|
39
|
-
assert_equal({}, widget.as_search)
|
40
|
-
end
|
41
|
-
|
42
|
-
Widget.new(id: '10', color: false).tap do |widget|
|
43
|
-
assert_equal({"color" => false}, widget.as_search)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def test_as_dirty_search
|
48
|
-
Widget.new(id: '10', color: 'green').tap do |widget|
|
49
|
-
assert_equal({'color' => 'green'}, widget.as_partial_update_document)
|
50
|
-
end
|
51
|
-
|
52
|
-
Widget.new(id: '10').tap do |widget|
|
53
|
-
assert_equal({}, widget.as_partial_update_document)
|
54
|
-
end
|
55
|
-
|
56
|
-
Widget.new(id: '10', color: '').tap do |widget|
|
57
|
-
assert_equal({'color' => nil}, widget.as_partial_update_document)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
class SpecialFieldsModel
|
62
|
-
include TestModel
|
63
|
-
|
64
|
-
class Author
|
65
|
-
def as_search
|
66
|
-
{name: 'Jonny'}
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
self.elastic_index.mapping[:properties].update(
|
71
|
-
author: {
|
72
|
-
type: :object
|
73
|
-
},
|
74
|
-
commenters: {
|
75
|
-
type: :nested
|
76
|
-
}
|
77
|
-
)
|
78
|
-
|
79
|
-
def author
|
80
|
-
Author.new
|
81
|
-
end
|
82
|
-
|
83
|
-
def commenters
|
84
|
-
[Author.new, Author.new]
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def test_as_search_with_special_fields
|
89
|
-
doc = SpecialFieldsModel.new.as_search
|
90
|
-
|
91
|
-
assert_equal({name: 'Jonny'}, doc[:author])
|
92
|
-
assert_equal([{name: 'Jonny'}, {name: 'Jonny'}], doc[:commenters])
|
93
|
-
end
|
94
|
-
|
95
33
|
class DisablingModel
|
96
34
|
include TestModel
|
97
35
|
|
98
|
-
attr_accessor :called_as_search
|
99
|
-
|
100
36
|
define_attributes [:height]
|
101
37
|
|
102
|
-
self.
|
38
|
+
self.doctype.mapping[:properties].update(
|
103
39
|
height: {
|
104
|
-
type: '
|
40
|
+
type: 'keyword'
|
105
41
|
}
|
106
42
|
)
|
107
43
|
|
108
|
-
def
|
109
|
-
|
44
|
+
def as_search_document
|
45
|
+
raise StandardError.new("Should never be called!")
|
110
46
|
super
|
111
47
|
end
|
112
|
-
|
113
|
-
end
|
114
|
-
|
115
|
-
def test_disabled_skip_document
|
116
|
-
DisablingModel.elastic_index.disable!
|
117
|
-
|
118
|
-
model = DisablingModel.new id: '5', height: '9 feets'
|
119
|
-
model.save
|
120
|
-
|
121
|
-
refute Widget.elastic_index.record_exists?(model.id)
|
122
|
-
refute model.called_as_search
|
123
48
|
end
|
124
|
-
end
|
49
|
+
end
|
@@ -8,7 +8,7 @@ class ElasticRecord::ConfigTest < MiniTest::Test
|
|
8
8
|
def test_models
|
9
9
|
ElasticRecord::Config.model_names = %w(Widget)
|
10
10
|
|
11
|
-
assert_equal [Warehouse, Widget, Project], ElasticRecord::Config.models
|
11
|
+
assert_equal [Warehouse, Widget, WidgetQuery, Project], ElasticRecord::Config.models
|
12
12
|
end
|
13
13
|
|
14
14
|
def test_servers
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class ElasticRecord::DoctypeTest < MiniTest::Test
|
4
|
+
def test_default_mapping
|
5
|
+
doctype = ElasticRecord::Doctype.new('widget')
|
6
|
+
|
7
|
+
refute_nil doctype.mapping[:properties]
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_default_analysis
|
11
|
+
doctype = ElasticRecord::Doctype.new('widget')
|
12
|
+
|
13
|
+
assert_empty doctype.analysis
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_merge_mapping
|
17
|
+
doctype = ElasticRecord::Doctype.new('widget')
|
18
|
+
doctype.mapping[:properties] = {
|
19
|
+
color: { type: 'string' },
|
20
|
+
name: { type: 'string' }
|
21
|
+
}
|
22
|
+
|
23
|
+
custom = { properties: { color: { type: 'integer' } }}
|
24
|
+
doctype.mapping = custom
|
25
|
+
|
26
|
+
expected = {
|
27
|
+
properties: {
|
28
|
+
color: { type: 'integer' },
|
29
|
+
name: { type: 'string' }
|
30
|
+
},
|
31
|
+
_all: {
|
32
|
+
enabled: false
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
assert_equal expected, doctype.mapping
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_percolator_doctype
|
40
|
+
doctype = ElasticRecord::Doctype.percolator_doctype
|
41
|
+
|
42
|
+
assert_equal 'queries', doctype.name
|
43
|
+
assert_equal ElasticRecord::Doctype::PERCOLATOR_MAPPING, doctype.mapping
|
44
|
+
end
|
45
|
+
end
|
@@ -28,7 +28,7 @@ class ElasticRecord::Index::DocumentsTest < MiniTest::Test
|
|
28
28
|
index.update_document('abc', color: 'blue')
|
29
29
|
|
30
30
|
expected = {'warehouse_id' => '5', 'color' => 'blue'}
|
31
|
-
assert_equal expected, index.get('abc')['_source']
|
31
|
+
assert_equal expected, index.get('abc', Widget.doctype)['_source']
|
32
32
|
end
|
33
33
|
|
34
34
|
def test_delete_document
|
@@ -1,23 +1,26 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
3
|
class ElasticRecord::Index::MappingTest < MiniTest::Test
|
4
|
-
def
|
5
|
-
|
4
|
+
def test_get_mapping
|
5
|
+
expected = {
|
6
|
+
"widget" => {
|
7
|
+
"_all" => { "enabled" => false },
|
8
|
+
"properties" => {
|
9
|
+
"color" => { "type" => "keyword" },
|
10
|
+
"name" => {
|
11
|
+
"type" => "keyword",
|
12
|
+
"fields" => { "analyzed" => { "type" => "text" } }
|
13
|
+
},
|
14
|
+
"warehouse_id" => { "type" => "keyword" }
|
15
|
+
}
|
16
|
+
}
|
17
|
+
}
|
6
18
|
|
7
|
-
|
8
|
-
end
|
9
|
-
|
10
|
-
def test_merge_mapping
|
11
|
-
index.mapping.clear
|
12
|
-
index.mapping[:properties] = {color: {type: 'string'}}
|
13
|
-
|
14
|
-
custom = {properties: {color: {type: 'integer'}}, other: 'stuff'}
|
15
|
-
index.mapping = custom
|
16
|
-
|
17
|
-
assert_equal custom, index.mapping
|
19
|
+
assert_equal expected, index.get_mapping
|
18
20
|
end
|
19
21
|
|
20
22
|
private
|
23
|
+
|
21
24
|
def index
|
22
25
|
@index ||= ElasticRecord::Index.new(Widget)
|
23
26
|
end
|