elastic_record 4.0.0 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|