elastic_record 5.4.0 → 5.5.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/Gemfile +3 -3
- data/README.md +1 -1
- data/Rakefile +1 -0
- data/elastic_record.gemspec +1 -1
- data/lib/elastic_record/callbacks.rb +1 -5
- data/lib/elastic_record/config.rb +6 -11
- data/lib/elastic_record/from_search_hit.rb +62 -0
- data/lib/elastic_record/index/analyze.rb +0 -10
- data/lib/elastic_record/index/documents.rb +16 -5
- data/lib/elastic_record/index/settings.rb +1 -5
- data/lib/elastic_record/index.rb +16 -2
- data/lib/elastic_record/model.rb +5 -0
- data/lib/elastic_record/percolator_model.rb +8 -9
- data/lib/elastic_record/relation/batches.rb +9 -3
- data/lib/elastic_record/relation/calculations.rb +14 -0
- data/lib/elastic_record/relation.rb +2 -1
- data/lib/elastic_record/search_hits.rb +1 -12
- data/lib/elastic_record.rb +1 -0
- data/test/dummy/app/models/project.rb +38 -3
- data/test/elastic_record/aggregation_response/single_value_aggregation_test.rb +9 -0
- data/test/elastic_record/config_test.rb +1 -1
- data/test/elastic_record/from_search_hits_test.rb +55 -0
- data/test/elastic_record/index/documents_test.rb +19 -1
- data/{lib → test}/elastic_record/index/mapping_type_test.rb +0 -0
- data/test/elastic_record/index/settings_test.rb +9 -9
- data/test/elastic_record/index_test.rb +6 -0
- data/test/elastic_record/model_test.rb +7 -0
- data/test/elastic_record/relation/batches_test.rb +8 -0
- data/test/elastic_record/relation/calculations_test.rb +11 -0
- metadata +9 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ea174acd40e5c2ec841c31085fea2a2994e0d05a705042d5ddf044e8c8962376
|
4
|
+
data.tar.gz: 1adb61c8170f1e966a7acb0c7c68ac95cc5f93181a81d6118f166de0cdf45a6a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 741a6d678b18f9c373e7bc6412e98ab7ec5b97241af2fde09c84fb5b5baebac69d5236a893886c88ed73c37d81f4e426d4182f5818659cb5f675e820494e5d06
|
7
|
+
data.tar.gz: 848de3cb5054a6997aa8022721bf7dff2c40740921a127611033ec87dcda6e862945697ef19414c775b7b8c970671e19f251d6812cd193ad3eb797c52c9e95b8
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -209,7 +209,7 @@ When one model inherits from another, ElasticRecord makes some assumptions about
|
|
209
209
|
* `alias_name` - Same as parent
|
210
210
|
* `mapping` - Same as parent
|
211
211
|
* `mapping_type` - Same as parent
|
212
|
-
* `settings`
|
212
|
+
* `settings` - Same as parent
|
213
213
|
|
214
214
|
These can all be overridden. For instance, it might be desirable for the child documents to be in a separate index.
|
215
215
|
|
data/Rakefile
CHANGED
data/elastic_record.gemspec
CHANGED
@@ -4,7 +4,7 @@ module ElasticRecord
|
|
4
4
|
return unless base.respond_to?(:after_save) && base.respond_to?(:after_destroy)
|
5
5
|
|
6
6
|
base.class_eval do
|
7
|
-
after_create :
|
7
|
+
after_create :index_to_elasticsearch
|
8
8
|
after_update :update_index_document, if: -> { respond_to?(:saved_changes?) ? saved_changes? : changed? }
|
9
9
|
after_destroy :delete_index_document
|
10
10
|
end
|
@@ -12,10 +12,6 @@ module ElasticRecord
|
|
12
12
|
|
13
13
|
private
|
14
14
|
|
15
|
-
def create_index_document
|
16
|
-
self.class.elastic_index.index_record self
|
17
|
-
end
|
18
|
-
|
19
15
|
def update_index_document
|
20
16
|
method = self.class.elastic_index.partial_updates ? :update_record : :index_record
|
21
17
|
|
@@ -2,17 +2,11 @@ require 'active_support/core_ext/class/attribute'
|
|
2
2
|
|
3
3
|
module ElasticRecord
|
4
4
|
class Config
|
5
|
-
class_attribute :connection_options
|
6
|
-
|
7
|
-
|
8
|
-
class_attribute :
|
9
|
-
|
10
|
-
|
11
|
-
class_attribute :model_names
|
12
|
-
self.model_names = []
|
13
|
-
|
14
|
-
class_attribute :scroll_keep_alive
|
15
|
-
self.scroll_keep_alive = '5m'
|
5
|
+
class_attribute :connection_options, default: {}
|
6
|
+
class_attribute :default_index_settings, default: {}
|
7
|
+
class_attribute :model_names, default: []
|
8
|
+
class_attribute :scroll_keep_alive, default: '2m'
|
9
|
+
class_attribute :index_suffix
|
16
10
|
|
17
11
|
class << self
|
18
12
|
def models
|
@@ -32,6 +26,7 @@ module ElasticRecord
|
|
32
26
|
|
33
27
|
def settings=(settings)
|
34
28
|
self.servers = settings['servers']
|
29
|
+
self.index_suffix = settings['index_suffix']
|
35
30
|
self.connection_options = settings
|
36
31
|
|
37
32
|
if settings['scroll_keep_alive'].present?
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module ElasticRecord
|
2
|
+
module FromSearchHit
|
3
|
+
|
4
|
+
def from_search_hit(hit)
|
5
|
+
hit = hit['_source'].merge('id' => hit['_id'])
|
6
|
+
|
7
|
+
attrs = value_from_search_hit_object(hit)
|
8
|
+
|
9
|
+
if respond_to?(:instantiate)
|
10
|
+
instantiate(attrs)
|
11
|
+
else
|
12
|
+
self.new.tap do |record|
|
13
|
+
attrs.each do |k, v|
|
14
|
+
record.send("#{k}=", v) if record.respond_to?("#{k}=")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def value_from_search_hit_object(hit)
|
23
|
+
hit.each do |field, value|
|
24
|
+
next unless value
|
25
|
+
|
26
|
+
case value
|
27
|
+
when Hash
|
28
|
+
hit[field] = value_from_search_hit(value)
|
29
|
+
when Array # type: 'nested'
|
30
|
+
value.each do |element|
|
31
|
+
if element.is_a? Hash
|
32
|
+
value_from_search_hit_object(element)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
hit
|
39
|
+
end
|
40
|
+
|
41
|
+
def value_from_search_hit(value)
|
42
|
+
case value['gte'] # the gte lower bound is never nil
|
43
|
+
when String
|
44
|
+
value_for_date_range(value)
|
45
|
+
when Integer
|
46
|
+
value_for_range(value)
|
47
|
+
else # type: 'object'
|
48
|
+
value_from_search_hit_object(value)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def value_for_range(value)
|
53
|
+
value['gte'] = -Float::INFINITY if value['gte'].nil?
|
54
|
+
value['lte'] = Float::INFINITY if value['lte'].nil?
|
55
|
+
value['gte']..value['lte']
|
56
|
+
end
|
57
|
+
|
58
|
+
def value_for_date_range(value)
|
59
|
+
Date.parse(value['gte'])..Date.parse(value['lte'])
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -1,16 +1,6 @@
|
|
1
1
|
module ElasticRecord
|
2
2
|
class Index
|
3
3
|
module Analyze
|
4
|
-
attr_accessor :analysis
|
5
|
-
|
6
|
-
def analysis
|
7
|
-
@analysis ||= {}
|
8
|
-
end
|
9
|
-
|
10
|
-
def analysis=(custom_analysis)
|
11
|
-
analysis.deep_merge!(custom_analysis)
|
12
|
-
end
|
13
|
-
|
14
4
|
def analyze(params)
|
15
5
|
json = connection.json_get "/#{alias_name}/_analyze", params
|
16
6
|
json['tokens'].map { |token_hash| token_hash['token'] }
|
@@ -3,7 +3,7 @@ require 'active_support/core_ext/object/to_query'
|
|
3
3
|
module ElasticRecord
|
4
4
|
class Index
|
5
5
|
class ScrollEnumerator
|
6
|
-
attr_reader :
|
6
|
+
attr_reader :keep_alive, :batch_size, :scroll_id
|
7
7
|
def initialize(elastic_index, search: nil, scroll_id: nil, keep_alive:, batch_size:)
|
8
8
|
@elastic_index = elastic_index
|
9
9
|
@search = search
|
@@ -16,6 +16,8 @@ module ElasticRecord
|
|
16
16
|
while (hits = request_more_hits.hits).any?
|
17
17
|
hits.each_slice(batch_size, &block)
|
18
18
|
end
|
19
|
+
|
20
|
+
@elastic_index.delete_scroll(scroll_id)
|
19
21
|
end
|
20
22
|
|
21
23
|
def request_more_ids
|
@@ -27,13 +29,18 @@ module ElasticRecord
|
|
27
29
|
end
|
28
30
|
|
29
31
|
def request_next_scroll
|
30
|
-
if scroll_id
|
31
|
-
response = initial_search_response
|
32
|
-
else
|
32
|
+
if scroll_id
|
33
33
|
response = @elastic_index.scroll(scroll_id, keep_alive)
|
34
|
+
|
35
|
+
if response['_scroll_id'] != scroll_id
|
36
|
+
@elastic_index.delete_scroll(scroll_id)
|
37
|
+
end
|
38
|
+
else
|
39
|
+
response = initial_search_response
|
34
40
|
end
|
35
41
|
|
36
|
-
@scroll_id =
|
42
|
+
@scroll_id = response['_scroll_id']
|
43
|
+
|
37
44
|
response
|
38
45
|
end
|
39
46
|
|
@@ -167,6 +174,10 @@ module ElasticRecord
|
|
167
174
|
end
|
168
175
|
end
|
169
176
|
|
177
|
+
def delete_scroll(scroll_id)
|
178
|
+
connection.json_delete('/_search/scroll', { scroll_id: scroll_id })
|
179
|
+
end
|
180
|
+
|
170
181
|
def bulk(options = {}, &block)
|
171
182
|
if current_bulk_batch
|
172
183
|
yield
|
@@ -6,11 +6,7 @@ module ElasticRecord
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def settings
|
9
|
-
@settings ||=
|
10
|
-
result = ElasticRecord::Config.default_index_settings.deep_dup
|
11
|
-
result['analysis'] = analysis if analysis.any?
|
12
|
-
result
|
13
|
-
end
|
9
|
+
@settings ||= ElasticRecord::Config.default_index_settings.deep_dup
|
14
10
|
end
|
15
11
|
|
16
12
|
def update_settings(index_name = alias_name, settings: self.settings)
|
data/lib/elastic_record/index.rb
CHANGED
@@ -50,11 +50,11 @@ module ElasticRecord
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def alias_name=(name)
|
53
|
-
@alias_name = name
|
53
|
+
@alias_name = add_suffix(name)
|
54
54
|
end
|
55
55
|
|
56
56
|
def alias_name
|
57
|
-
@alias_name ||= model.base_class.name.demodulize.underscore.pluralize
|
57
|
+
@alias_name ||= add_suffix(model.base_class.name.demodulize.underscore.pluralize)
|
58
58
|
end
|
59
59
|
|
60
60
|
def disable!
|
@@ -68,6 +68,11 @@ module ElasticRecord
|
|
68
68
|
def load_from_source!
|
69
69
|
self.load_from_source = true
|
70
70
|
model.singleton_class.delegate :find, :find_by, :find_each, :find_in_batches, :first, to: :elastic_search
|
71
|
+
|
72
|
+
model.instance_eval do
|
73
|
+
def _insert_record(*args); end
|
74
|
+
def _update_record(*args); end
|
75
|
+
end
|
71
76
|
end
|
72
77
|
|
73
78
|
def loading_from_source(&block)
|
@@ -91,6 +96,15 @@ module ElasticRecord
|
|
91
96
|
|
92
97
|
private
|
93
98
|
|
99
|
+
def add_suffix(name)
|
100
|
+
suffix = ElasticRecord::Config.index_suffix
|
101
|
+
if suffix && !name.end_with?(suffix)
|
102
|
+
name + "_#{suffix}"
|
103
|
+
else
|
104
|
+
name
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
94
108
|
def new_index_name
|
95
109
|
"#{alias_name}_#{Time.now.utc.strftime('%Y%m%d_%H%M%S')}"
|
96
110
|
end
|
data/lib/elastic_record/model.rb
CHANGED
@@ -4,6 +4,7 @@ module ElasticRecord
|
|
4
4
|
base.class_eval do
|
5
5
|
extend Searching
|
6
6
|
extend ClassMethods
|
7
|
+
extend FromSearchHit
|
7
8
|
include Callbacks
|
8
9
|
include AsDocument
|
9
10
|
|
@@ -38,6 +39,10 @@ module ElasticRecord
|
|
38
39
|
end
|
39
40
|
end
|
40
41
|
|
42
|
+
def index_to_elasticsearch
|
43
|
+
elastic_index.index_record(self)
|
44
|
+
end
|
45
|
+
|
41
46
|
def arelastic
|
42
47
|
self.class.arelastic
|
43
48
|
end
|
@@ -16,15 +16,14 @@ module ElasticRecord
|
|
16
16
|
}
|
17
17
|
}
|
18
18
|
def elastic_index
|
19
|
-
@elastic_index ||=
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end
|
19
|
+
@elastic_index ||= begin
|
20
|
+
index = ElasticRecord::Index.new(self)
|
21
|
+
index.mapping = DEFAULT_PERCOLATOR_MAPPING
|
22
|
+
index.mapping = percolates_model.elastic_index.mapping
|
23
|
+
index.settings = percolates_model.elastic_index.settings
|
24
|
+
index.partial_updates = false
|
25
|
+
index
|
26
|
+
end
|
28
27
|
end
|
29
28
|
|
30
29
|
def percolate(document)
|
@@ -8,14 +8,20 @@ module ElasticRecord
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def find_in_batches(options = {})
|
11
|
-
|
12
|
-
yield
|
11
|
+
find_hits_in_batches(options) do |hits|
|
12
|
+
yield hits.to_records
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
16
|
def find_ids_in_batches(options = {})
|
17
|
+
find_hits_in_batches(options) do |hits|
|
18
|
+
yield hits.to_ids
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def find_hits_in_batches(options = {})
|
17
23
|
build_scroll_enumerator(options).each_slice do |hits|
|
18
|
-
yield SearchHits.new(klass, hits)
|
24
|
+
yield SearchHits.new(klass, hits)
|
19
25
|
end
|
20
26
|
end
|
21
27
|
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module ElasticRecord
|
2
|
+
class Relation
|
3
|
+
module Calculations
|
4
|
+
# Retrieve a single aggregation:
|
5
|
+
#
|
6
|
+
# Widget.elastic_search.calculate(cardinality: {field: color'}).value
|
7
|
+
# => 3
|
8
|
+
def calculate(aggregation)
|
9
|
+
agg_name = SecureRandom.hex(6)
|
10
|
+
aggregate(agg_name => aggregation).aggregations[agg_name]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'elastic_record/relation/value_methods'
|
2
2
|
require 'elastic_record/relation/batches'
|
3
|
+
require 'elastic_record/relation/calculations'
|
3
4
|
require 'elastic_record/relation/delegation'
|
4
5
|
require 'elastic_record/relation/finder_methods'
|
5
6
|
require 'elastic_record/relation/hits'
|
@@ -9,7 +10,7 @@ require 'elastic_record/relation/search_methods'
|
|
9
10
|
|
10
11
|
module ElasticRecord
|
11
12
|
class Relation
|
12
|
-
include Batches, Delegation, FinderMethods, Hits, Merging, SearchMethods
|
13
|
+
include Batches, Calculations, Delegation, FinderMethods, Hits, Merging, SearchMethods
|
13
14
|
|
14
15
|
attr_reader :klass, :values
|
15
16
|
|
@@ -19,21 +19,10 @@ module ElasticRecord
|
|
19
19
|
|
20
20
|
def to_records
|
21
21
|
if model.elastic_index.load_from_source
|
22
|
-
hits.map { |hit|
|
22
|
+
hits.map { |hit| model.from_search_hit(hit) }
|
23
23
|
else
|
24
24
|
model.find to_ids
|
25
25
|
end
|
26
26
|
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
def load_from_hit(hit)
|
31
|
-
model.new.tap do |record|
|
32
|
-
record.id = hit['_id']
|
33
|
-
hit['_source'].each do |k, v|
|
34
|
-
record.send("#{k}=", v) if record.respond_to?("#{k}=")
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
27
|
end
|
39
28
|
end
|
data/lib/elastic_record.rb
CHANGED
@@ -8,11 +8,46 @@ class Project
|
|
8
8
|
include ActiveModel::Model
|
9
9
|
include ElasticRecord::Model
|
10
10
|
elastic_index.load_from_source!
|
11
|
+
elastic_index.mapping = {
|
12
|
+
properties: {
|
13
|
+
'name' => {
|
14
|
+
type: 'text'
|
15
|
+
},
|
16
|
+
'estimated_start_date' => {
|
17
|
+
type: 'date_range'
|
18
|
+
},
|
19
|
+
'team_members' => {
|
20
|
+
type: 'nested',
|
21
|
+
properties: {
|
22
|
+
'name' => { type: 'text' },
|
23
|
+
'estimated_age' => {
|
24
|
+
type: 'integer_range'
|
25
|
+
}
|
26
|
+
}
|
27
|
+
},
|
28
|
+
'manager' => {
|
29
|
+
type: 'object',
|
30
|
+
properties: {
|
31
|
+
'name' => { type: 'text' },
|
32
|
+
'estimated_age' => {
|
33
|
+
type: 'integer_range'
|
34
|
+
}
|
35
|
+
}
|
36
|
+
}
|
37
|
+
}
|
38
|
+
}
|
11
39
|
|
12
|
-
attr_accessor :id,
|
40
|
+
attr_accessor :id,
|
41
|
+
:name,
|
42
|
+
:estimated_start_date,
|
43
|
+
:team_members,
|
44
|
+
:manager
|
13
45
|
alias_method :as_json, :as_search_document
|
14
46
|
|
15
|
-
|
16
|
-
|
47
|
+
class TeamMember
|
48
|
+
include ActiveModel::Model
|
49
|
+
include ElasticRecord::Model
|
50
|
+
|
51
|
+
attr_accessor :name, :estimated_age
|
17
52
|
end
|
18
53
|
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class ElasticRecord::AggregationResponse::SingleValueAggregationTest < MiniTest::Test
|
4
|
+
def test_value
|
5
|
+
agg = ElasticRecord::AggregationResponse::SingleValueAggregation.new 'average_price', 'value' => 4
|
6
|
+
|
7
|
+
assert_equal 4, agg.value
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class ElasticRecord::FromSearchHitsTest < MiniTest::Test
|
4
|
+
def setup
|
5
|
+
super
|
6
|
+
@project = Project.new(
|
7
|
+
name: 'foo',
|
8
|
+
estimated_start_date: Date.new(2019, 1, 1)..Date.new(2019, 2, 1),
|
9
|
+
team_members: team_members,
|
10
|
+
manager: manager
|
11
|
+
)
|
12
|
+
Project.elastic_index.index_record(@project)
|
13
|
+
end
|
14
|
+
|
15
|
+
def teardown
|
16
|
+
Project.elastic_index.delete_by_query query: { match_all: {} }
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_ranges
|
20
|
+
document = Project.elastic_relation.search_hits.to_records.first
|
21
|
+
|
22
|
+
assert_equal 'foo', document.name
|
23
|
+
assert_equal @project.estimated_start_date, document.estimated_start_date
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_nested_ranges
|
27
|
+
document = Project.elastic_relation.search_hits.to_records.first
|
28
|
+
team_members = document.team_members.sort_by { |member| member['name'] }
|
29
|
+
|
30
|
+
assert_equal 26..29, team_members.first['estimated_age']
|
31
|
+
assert_equal 25..30, team_members.second['estimated_age']
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_object_ranges
|
35
|
+
document = Project.elastic_relation.search_hits.to_records.first
|
36
|
+
|
37
|
+
assert_equal 25..30, document.manager['estimated_age']
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def manager
|
43
|
+
Project::TeamMember.new(
|
44
|
+
name: 'Fred',
|
45
|
+
estimated_age: 25..30
|
46
|
+
)
|
47
|
+
end
|
48
|
+
|
49
|
+
def team_members
|
50
|
+
[
|
51
|
+
Project::TeamMember.new(name: 'John', estimated_age: 25..30),
|
52
|
+
Project::TeamMember.new(name: 'Jill', estimated_age: 26..29)
|
53
|
+
]
|
54
|
+
end
|
55
|
+
end
|
@@ -99,7 +99,25 @@ class ElasticRecord::Index::DocumentsTest < MiniTest::Test
|
|
99
99
|
)
|
100
100
|
|
101
101
|
scroll_enumerator.request_more_hits
|
102
|
-
index.
|
102
|
+
index.delete_scroll(scroll_enumerator.scroll_id)
|
103
|
+
assert_raises ElasticRecord::ExpiredScrollError do
|
104
|
+
scroll_enumerator.request_more_hits
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_each_slice
|
109
|
+
10.times { |i| index.index_document("bob#{i}", color: 'red') }
|
110
|
+
batches = []
|
111
|
+
|
112
|
+
scroll_enumerator = index.build_scroll_enumerator(search: {'query' => {query_string: {query: 'color:red'}}}, batch_size: 1)
|
113
|
+
|
114
|
+
scroll_enumerator.each_slice do |slice|
|
115
|
+
batches << slice
|
116
|
+
end
|
117
|
+
|
118
|
+
assert_equal 10, batches.size
|
119
|
+
|
120
|
+
# Assert context was removed
|
103
121
|
assert_raises ElasticRecord::ExpiredScrollError do
|
104
122
|
scroll_enumerator.request_more_hits
|
105
123
|
end
|
File without changes
|
@@ -9,11 +9,11 @@ class ElasticRecord::Index::SettingsTest < MiniTest::Test
|
|
9
9
|
class ModelWithAnalyzers
|
10
10
|
include TestModel
|
11
11
|
|
12
|
-
elastic_index.analysis = {
|
13
|
-
"analyzer"
|
14
|
-
"my_custom_analyzer"
|
15
|
-
"type"
|
16
|
-
"tokenizer"
|
12
|
+
elastic_index.settings['analysis'] = {
|
13
|
+
"analyzer" => {
|
14
|
+
"my_custom_analyzer" => {
|
15
|
+
"type" => "custom",
|
16
|
+
"tokenizer" => "standard"
|
17
17
|
}
|
18
18
|
}
|
19
19
|
}
|
@@ -26,10 +26,10 @@ class ElasticRecord::Index::SettingsTest < MiniTest::Test
|
|
26
26
|
def test_settings
|
27
27
|
expected = {
|
28
28
|
"analysis" => {
|
29
|
-
"analyzer"
|
30
|
-
"my_custom_analyzer"
|
31
|
-
"type"
|
32
|
-
"tokenizer"
|
29
|
+
"analyzer" => {
|
30
|
+
"my_custom_analyzer" => {
|
31
|
+
"type" => "custom",
|
32
|
+
"tokenizer" => "standard"
|
33
33
|
}
|
34
34
|
}
|
35
35
|
},
|
@@ -9,6 +9,12 @@ class ElasticRecord::IndexTest < MiniTest::Test
|
|
9
9
|
|
10
10
|
def test_alias_name
|
11
11
|
assert_equal 'widgets', index.alias_name
|
12
|
+
|
13
|
+
ElasticRecord::Config.index_suffix = 'test'
|
14
|
+
index.alias_name = "other_name"
|
15
|
+
assert_equal 'other_name_test', index.alias_name
|
16
|
+
ensure
|
17
|
+
ElasticRecord::Config.index_suffix = nil
|
12
18
|
end
|
13
19
|
|
14
20
|
def test_disable
|
@@ -24,4 +24,11 @@ class ElasticRecord::ModelTest < MiniTest::Test
|
|
24
24
|
assert_equal InheritedModel, InheritedModel.elastic_index.model
|
25
25
|
assert_equal 'widget', InheritedModel.elastic_index.mapping_type
|
26
26
|
end
|
27
|
+
|
28
|
+
def test_index_to_elasticsearch
|
29
|
+
project = Project.new(name: 'scorpio')
|
30
|
+
project.index_to_elasticsearch
|
31
|
+
|
32
|
+
assert_equal [project.name], Project.filter(name: 'scorpio').map(&:name)
|
33
|
+
end
|
27
34
|
end
|
@@ -16,6 +16,14 @@ class ElasticRecord::Relation::BatchesTest < MiniTest::Test
|
|
16
16
|
# assert_equal [@red_widget, @blue_widget, @green_widget].to_set, results.to_set
|
17
17
|
# end
|
18
18
|
|
19
|
+
def test_find_hits_in_batches
|
20
|
+
results = []
|
21
|
+
Widget.elastic_relation.find_hits_in_batches do |hits|
|
22
|
+
results << hits
|
23
|
+
end
|
24
|
+
assert_equal [[@red_widget, @blue_widget, @green_widget].to_set], results.map(&:to_records).map(&:to_set)
|
25
|
+
end
|
26
|
+
|
19
27
|
def test_find_ids_in_batches
|
20
28
|
results = []
|
21
29
|
Widget.elastic_relation.find_ids_in_batches do |ids|
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class ElasticRecord::Relation::CalculationsTest < MiniTest::Test
|
4
|
+
def test_calculate
|
5
|
+
Widget.create!(color: 'red')
|
6
|
+
Widget.create!(color: 'red')
|
7
|
+
Widget.create!(color: 'blue')
|
8
|
+
|
9
|
+
assert_equal 2, Widget.elastic_relation.calculate('cardinality' => {'field' => 'color'}).value
|
10
|
+
end
|
11
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: elastic_record
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Infogroup
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2019-04-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: arelastic
|
@@ -67,6 +67,7 @@ files:
|
|
67
67
|
- lib/elastic_record/config.rb
|
68
68
|
- lib/elastic_record/connection.rb
|
69
69
|
- lib/elastic_record/errors.rb
|
70
|
+
- lib/elastic_record/from_search_hit.rb
|
70
71
|
- lib/elastic_record/index.rb
|
71
72
|
- lib/elastic_record/index/analyze.rb
|
72
73
|
- lib/elastic_record/index/deferred.rb
|
@@ -74,7 +75,6 @@ files:
|
|
74
75
|
- lib/elastic_record/index/manage.rb
|
75
76
|
- lib/elastic_record/index/mapping.rb
|
76
77
|
- lib/elastic_record/index/mapping_type.rb
|
77
|
-
- lib/elastic_record/index/mapping_type_test.rb
|
78
78
|
- lib/elastic_record/index/settings.rb
|
79
79
|
- lib/elastic_record/log_subscriber.rb
|
80
80
|
- lib/elastic_record/lucene.rb
|
@@ -84,6 +84,7 @@ files:
|
|
84
84
|
- lib/elastic_record/railties/controller_runtime.rb
|
85
85
|
- lib/elastic_record/relation.rb
|
86
86
|
- lib/elastic_record/relation/batches.rb
|
87
|
+
- lib/elastic_record/relation/calculations.rb
|
87
88
|
- lib/elastic_record/relation/delegation.rb
|
88
89
|
- lib/elastic_record/relation/finder_methods.rb
|
89
90
|
- lib/elastic_record/relation/hits.rb
|
@@ -151,14 +152,17 @@ files:
|
|
151
152
|
- test/elastic_record/aggregation_response/bucket_test.rb
|
152
153
|
- test/elastic_record/aggregation_response/multi_bucket_aggregation_test.rb
|
153
154
|
- test/elastic_record/aggregation_response/single_bucket_aggregation_test.rb
|
155
|
+
- test/elastic_record/aggregation_response/single_value_aggregation_test.rb
|
154
156
|
- test/elastic_record/as_document_test.rb
|
155
157
|
- test/elastic_record/callbacks_test.rb
|
156
158
|
- test/elastic_record/config_test.rb
|
157
159
|
- test/elastic_record/connection_test.rb
|
160
|
+
- test/elastic_record/from_search_hits_test.rb
|
158
161
|
- test/elastic_record/index/analyze_test.rb
|
159
162
|
- test/elastic_record/index/documents_test.rb
|
160
163
|
- test/elastic_record/index/manage_test.rb
|
161
164
|
- test/elastic_record/index/mapping_test.rb
|
165
|
+
- test/elastic_record/index/mapping_type_test.rb
|
162
166
|
- test/elastic_record/index/settings_test.rb
|
163
167
|
- test/elastic_record/index_test.rb
|
164
168
|
- test/elastic_record/integration/active_record_test.rb
|
@@ -168,6 +172,7 @@ files:
|
|
168
172
|
- test/elastic_record/percolator_model_test.rb
|
169
173
|
- test/elastic_record/railties/controller_runtime_test.rb
|
170
174
|
- test/elastic_record/relation/batches_test.rb
|
175
|
+
- test/elastic_record/relation/calculations_test.rb
|
171
176
|
- test/elastic_record/relation/delegation_test.rb
|
172
177
|
- test/elastic_record/relation/finder_methods_test.rb
|
173
178
|
- test/elastic_record/relation/hits_test.rb
|
@@ -196,8 +201,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
196
201
|
- !ruby/object:Gem::Version
|
197
202
|
version: 1.8.11
|
198
203
|
requirements: []
|
199
|
-
|
200
|
-
rubygems_version: 2.7.6
|
204
|
+
rubygems_version: 3.0.3
|
201
205
|
signing_key:
|
202
206
|
specification_version: 4
|
203
207
|
summary: An Elasticsearch querying ORM
|