chewy 0.4.1 → 0.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/.travis.yml +3 -3
- data/CHANGELOG.md +43 -1
- data/Gemfile +3 -0
- data/README.md +49 -11
- data/chewy.gemspec +1 -2
- data/gemfiles/Gemfile.rails-3.2 +1 -0
- data/gemfiles/Gemfile.rails-4.0 +1 -0
- data/lib/chewy.rb +8 -2
- data/lib/chewy/backports/deep_dup.rb +46 -0
- data/lib/chewy/backports/duplicable.rb +90 -0
- data/lib/chewy/config.rb +33 -6
- data/lib/chewy/errors.rb +1 -1
- data/lib/chewy/fields/base.rb +19 -7
- data/lib/chewy/fields/root.rb +13 -0
- data/lib/chewy/index/actions.rb +14 -6
- data/lib/chewy/index/search.rb +3 -2
- data/lib/chewy/query.rb +131 -17
- data/lib/chewy/query/compose.rb +27 -17
- data/lib/chewy/query/criteria.rb +34 -22
- data/lib/chewy/query/loading.rb +94 -10
- data/lib/chewy/query/nodes/exists.rb +1 -1
- data/lib/chewy/query/nodes/has_relation.rb +1 -1
- data/lib/chewy/query/nodes/missing.rb +1 -1
- data/lib/chewy/query/pagination.rb +8 -38
- data/lib/chewy/query/pagination/kaminari.rb +37 -0
- data/lib/chewy/runtime.rb +9 -0
- data/lib/chewy/runtime/version.rb +25 -0
- data/lib/chewy/type/adapter/active_record.rb +21 -7
- data/lib/chewy/type/adapter/base.rb +1 -1
- data/lib/chewy/type/adapter/object.rb +9 -6
- data/lib/chewy/type/import.rb +7 -4
- data/lib/chewy/type/mapping.rb +9 -9
- data/lib/chewy/type/wrapper.rb +1 -1
- data/lib/chewy/version.rb +1 -1
- data/lib/tasks/chewy.rake +40 -21
- data/spec/chewy/config_spec.rb +1 -1
- data/spec/chewy/fields/base_spec.rb +273 -8
- data/spec/chewy/index/actions_spec.rb +1 -2
- data/spec/chewy/index/aliases_spec.rb +0 -1
- data/spec/chewy/index/search_spec.rb +0 -8
- data/spec/chewy/index/settings_spec.rb +0 -2
- data/spec/chewy/index_spec.rb +0 -2
- data/spec/chewy/query/criteria_spec.rb +85 -18
- data/spec/chewy/query/loading_spec.rb +26 -9
- data/spec/chewy/query/nodes/and_spec.rb +2 -2
- data/spec/chewy/query/nodes/exists_spec.rb +6 -6
- data/spec/chewy/query/nodes/missing_spec.rb +4 -4
- data/spec/chewy/query/nodes/or_spec.rb +2 -2
- data/spec/chewy/query/pagination/kaminari_spec.rb +55 -0
- data/spec/chewy/query/pagination_spec.rb +15 -22
- data/spec/chewy/query_spec.rb +121 -52
- data/spec/chewy/rspec/update_index_spec.rb +0 -1
- data/spec/chewy/runtime/version_spec.rb +48 -0
- data/spec/chewy/runtime_spec.rb +9 -0
- data/spec/chewy/type/adapter/active_record_spec.rb +52 -0
- data/spec/chewy/type/adapter/object_spec.rb +33 -0
- data/spec/chewy/type/import_spec.rb +1 -3
- data/spec/chewy/type/mapping_spec.rb +4 -6
- data/spec/chewy/type/observe_spec.rb +0 -2
- data/spec/chewy/type/wrapper_spec.rb +0 -2
- data/spec/chewy/type_spec.rb +26 -5
- data/spec/chewy_spec.rb +0 -2
- data/spec/spec_helper.rb +2 -2
- metadata +15 -21
- data/lib/chewy/fields/default.rb +0 -10
- data/spec/chewy/fields/default_spec.rb +0 -6
data/lib/chewy/errors.rb
CHANGED
data/lib/chewy/fields/base.rb
CHANGED
@@ -4,23 +4,33 @@ module Chewy
|
|
4
4
|
attr_reader :name, :options, :value
|
5
5
|
|
6
6
|
def initialize(name, options = {})
|
7
|
-
@name, @options, @nested = name.to_sym, options, {}
|
7
|
+
@name, @options, @nested = name.to_sym, options.deep_symbolize_keys, {}
|
8
8
|
@value = @options.delete(:value)
|
9
9
|
end
|
10
10
|
|
11
11
|
def multi_field?
|
12
|
-
|
12
|
+
nested.any? && !object_field?
|
13
|
+
end
|
14
|
+
|
15
|
+
def object_field?
|
16
|
+
(nested.any? && options[:type].blank?) || options[:type].to_s == 'object'
|
17
|
+
end
|
18
|
+
|
19
|
+
def root_field?
|
20
|
+
false
|
13
21
|
end
|
14
22
|
|
15
23
|
def compose(object)
|
16
24
|
result = if value && value.is_a?(Proc)
|
17
25
|
value.arity == 0 ? object.instance_exec(&value) : value.call(object)
|
26
|
+
elsif object.is_a?(Hash)
|
27
|
+
object[name] || object[name.to_s]
|
18
28
|
else
|
19
29
|
object.send(name)
|
20
30
|
end
|
21
31
|
|
22
|
-
result = if result.
|
23
|
-
result.map { |object| nested_compose(object) }
|
32
|
+
result = if result.respond_to?(:to_ary)
|
33
|
+
result.to_ary.map { |object| nested_compose(object) }
|
24
34
|
else
|
25
35
|
nested_compose(result)
|
26
36
|
end if nested.any? && !multi_field?
|
@@ -37,16 +47,18 @@ module Chewy
|
|
37
47
|
end
|
38
48
|
|
39
49
|
def mappings_hash
|
40
|
-
|
50
|
+
mapping = nested.any? ? {
|
41
51
|
(multi_field? ? :fields : :properties) => nested.values.map(&:mappings_hash).inject(:merge)
|
42
52
|
} : {}
|
43
|
-
|
53
|
+
mapping.reverse_merge!(options)
|
54
|
+
mapping.reverse_merge!(type: (nested.any? ? 'object' : 'string')) unless root_field?
|
55
|
+
{name => mapping}
|
44
56
|
end
|
45
57
|
|
46
58
|
private
|
47
59
|
|
48
60
|
def nested_compose(value)
|
49
|
-
nested.values.map { |field| field.compose(value) }.inject(:merge)
|
61
|
+
nested.values.map { |field| field.compose(value) if value }.compact.inject(:merge)
|
50
62
|
end
|
51
63
|
end
|
52
64
|
end
|
data/lib/chewy/fields/root.rb
CHANGED
@@ -6,9 +6,22 @@ module Chewy
|
|
6
6
|
def initialize(name, options = {})
|
7
7
|
options.reverse_merge!(value: ->(_){_})
|
8
8
|
super(name, options)
|
9
|
+
options.delete(:type)
|
9
10
|
@dynamic_templates = []
|
10
11
|
end
|
11
12
|
|
13
|
+
def multi_field?
|
14
|
+
false
|
15
|
+
end
|
16
|
+
|
17
|
+
def object_field?
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
def root_field?
|
22
|
+
true
|
23
|
+
end
|
24
|
+
|
12
25
|
def mappings_hash
|
13
26
|
mappings = super
|
14
27
|
if dynamic_templates.any?
|
data/lib/chewy/index/actions.rb
CHANGED
@@ -56,10 +56,16 @@ module Chewy
|
|
56
56
|
options = args.extract_options!.reverse_merge!(alias: true)
|
57
57
|
name = build_index_name(suffix: args.first)
|
58
58
|
|
59
|
-
Chewy.
|
59
|
+
if Chewy::Runtime.version >= 1.1
|
60
|
+
body = index_params
|
61
|
+
body.merge!(aliases: {index_name => {}}) if options[:alias] && name != index_name
|
62
|
+
result = client.indices.create(index: name, body: body)
|
63
|
+
else
|
64
|
+
result = client.indices.create(index: name, body: index_params)
|
65
|
+
result &&= client.indices.put_alias(index: name, name: index_name) if options[:alias] && name != index_name
|
66
|
+
end
|
60
67
|
|
61
|
-
|
62
|
-
result &&= client.indices.put_alias(index: name, name: index_name) if options[:alias] && name != index_name
|
68
|
+
Chewy.wait_for_status if result
|
63
69
|
result
|
64
70
|
end
|
65
71
|
|
@@ -87,9 +93,9 @@ module Chewy
|
|
87
93
|
# UsersIndex.delete '01-2014' # deletes `users_01-2014` index
|
88
94
|
#
|
89
95
|
def delete! suffix = nil
|
90
|
-
|
91
|
-
|
92
|
-
|
96
|
+
result = client.indices.delete index: build_index_name(suffix: suffix)
|
97
|
+
Chewy.wait_for_status if result
|
98
|
+
result
|
93
99
|
end
|
94
100
|
|
95
101
|
# Deletes and recreates index. Supports suffixes.
|
@@ -128,6 +134,8 @@ module Chewy
|
|
128
134
|
# UsersIndex.import suffix: Time.now.to_i # imports data to index with specified suffix if such is exists
|
129
135
|
# UsersIndex.import batch_size: 300 # import batch size
|
130
136
|
#
|
137
|
+
# See [import.rb](lib/chewy/type/import.rb) for more details.
|
138
|
+
#
|
131
139
|
[:import, :import!].each do |method|
|
132
140
|
class_eval <<-METHOD, __FILE__, __LINE__ + 1
|
133
141
|
def #{method} options = {}
|
data/lib/chewy/index/search.rb
CHANGED
@@ -4,8 +4,9 @@ module Chewy
|
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
included do
|
7
|
-
singleton_class.delegate :explain, :limit, :offset, :
|
8
|
-
:
|
7
|
+
singleton_class.delegate :explain, :limit, :offset, :highlight, :rescore,
|
8
|
+
:facets, :aggregations, :none, :strategy, :query, :filter, :post_filter,
|
9
|
+
:order, :reorder, :only, :types, :suggest, to: :all
|
9
10
|
end
|
10
11
|
|
11
12
|
module ClassMethods
|
data/lib/chewy/query.rb
CHANGED
@@ -1,8 +1,3 @@
|
|
1
|
-
begin
|
2
|
-
require 'kaminari'
|
3
|
-
rescue LoadError
|
4
|
-
end
|
5
|
-
|
6
1
|
require 'chewy/query/criteria'
|
7
2
|
require 'chewy/query/filters'
|
8
3
|
require 'chewy/query/loading'
|
@@ -21,7 +16,17 @@ module Chewy
|
|
21
16
|
include Loading
|
22
17
|
include Pagination
|
23
18
|
|
24
|
-
|
19
|
+
RESULT_MERGER = lambda do |key, old_value, new_value|
|
20
|
+
if old_value.is_a?(Hash) && new_value.is_a?(Hash)
|
21
|
+
old_value.merge(new_value, &RESULT_MERGER)
|
22
|
+
elsif new_value.is_a?(Array) && new_value.count > 1
|
23
|
+
new_value
|
24
|
+
else
|
25
|
+
old_value.is_a?(Array) ? new_value : new_value.first
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
delegate :each, :count, :size, to: :_collection
|
25
30
|
alias_method :to_ary, :to_a
|
26
31
|
|
27
32
|
attr_reader :index, :options, :criteria
|
@@ -62,7 +67,7 @@ module Chewy
|
|
62
67
|
# UsersIndex::User.filter(term: {name: 'Johny'}).explain.first._explanation # => {...}
|
63
68
|
#
|
64
69
|
def explain value = nil
|
65
|
-
chain { criteria.
|
70
|
+
chain { criteria.update_request_options explain: (value.nil? ? true : value) }
|
66
71
|
end
|
67
72
|
|
68
73
|
# Sets query compilation mode for search request.
|
@@ -207,6 +212,18 @@ module Chewy
|
|
207
212
|
chain { criteria.update_options filter_mode: value }
|
208
213
|
end
|
209
214
|
|
215
|
+
# Acts the same way as `filter_mode`, but used for `post_filter`.
|
216
|
+
# Note that it fallbacks by default to `Chewy.filter_mode` if
|
217
|
+
# `Chewy.post_filter_mode` is nil.
|
218
|
+
#
|
219
|
+
# UsersIndex.post_filter{ name == 'Johny' }.post_filter{ age <= 42 }.post_filter_mode(:and)
|
220
|
+
# UsersIndex.post_filter{ name == 'Johny' }.post_filter{ age <= 42 }.post_filter_mode(:should)
|
221
|
+
# UsersIndex.post_filter{ name == 'Johny' }.post_filter{ age <= 42 }.post_filter_mode('50%')
|
222
|
+
#
|
223
|
+
def post_filter_mode value
|
224
|
+
chain { criteria.update_options post_filter_mode: value }
|
225
|
+
end
|
226
|
+
|
210
227
|
# Sets elasticsearch <tt>size</tt> search request param
|
211
228
|
# Default value is set in the elasticsearch and is 10.
|
212
229
|
#
|
@@ -217,7 +234,7 @@ module Chewy
|
|
217
234
|
# }}
|
218
235
|
#
|
219
236
|
def limit value
|
220
|
-
chain { criteria.
|
237
|
+
chain { criteria.update_request_options size: Integer(value) }
|
221
238
|
end
|
222
239
|
|
223
240
|
# Sets elasticsearch <tt>from</tt> search request param
|
@@ -229,7 +246,23 @@ module Chewy
|
|
229
246
|
# }}
|
230
247
|
#
|
231
248
|
def offset value
|
232
|
-
chain { criteria.
|
249
|
+
chain { criteria.update_request_options from: Integer(value) }
|
250
|
+
end
|
251
|
+
|
252
|
+
# Elasticsearch highlight query option support
|
253
|
+
#
|
254
|
+
# UsersIndex.query(...).highlight(fields: { ... })
|
255
|
+
#
|
256
|
+
def highlight value
|
257
|
+
chain { criteria.update_request_options highlight: value }
|
258
|
+
end
|
259
|
+
|
260
|
+
# Elasticsearch rescore query option support
|
261
|
+
#
|
262
|
+
# UsersIndex.query(...).rescore(query: { ... })
|
263
|
+
#
|
264
|
+
def rescore value
|
265
|
+
chain { criteria.update_request_options rescore: value }
|
233
266
|
end
|
234
267
|
|
235
268
|
# Adds facets section to the search request.
|
@@ -274,6 +307,27 @@ module Chewy
|
|
274
307
|
end
|
275
308
|
alias :aggs :aggregations
|
276
309
|
|
310
|
+
# Sets elasticsearch <tt>suggest</tt> search request param
|
311
|
+
#
|
312
|
+
# UsersIndex.suggest(name: {text: 'Joh', term: {field: 'name'}})
|
313
|
+
# # => {body: {
|
314
|
+
# query: {...},
|
315
|
+
# suggest: {
|
316
|
+
# text: 'Joh',
|
317
|
+
# term: {
|
318
|
+
# field: 'name'
|
319
|
+
# }
|
320
|
+
# }
|
321
|
+
# }}
|
322
|
+
#
|
323
|
+
def suggest params = nil
|
324
|
+
if params
|
325
|
+
chain { criteria.update_suggest params }
|
326
|
+
else
|
327
|
+
_response['suggest'] || {}
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
277
331
|
# Marks the criteria as having zero records. This scope always returns empty array
|
278
332
|
# without touching the elasticsearch server.
|
279
333
|
# All the chained calls of methods don't affect the result
|
@@ -288,6 +342,20 @@ module Chewy
|
|
288
342
|
chain { criteria.update_options none: true }
|
289
343
|
end
|
290
344
|
|
345
|
+
# Setups strategy for top-level filtered query
|
346
|
+
#
|
347
|
+
# UsersIndex.filter { name == 'Johny'}.strategy(:leap_frog)
|
348
|
+
# # => {body: {
|
349
|
+
# query: { filtered: {
|
350
|
+
# filter: { term: { name: 'Johny' } },
|
351
|
+
# strategy: 'leap_frog'
|
352
|
+
# } }
|
353
|
+
# }}
|
354
|
+
#
|
355
|
+
def strategy value = nil
|
356
|
+
chain { criteria.update_options strategy: value }
|
357
|
+
end
|
358
|
+
|
291
359
|
# Adds one or more query to the search request
|
292
360
|
# Internally queries are stored as an array
|
293
361
|
# While the full query compilation this array compiles
|
@@ -319,7 +387,7 @@ module Chewy
|
|
319
387
|
# While the full query compilation this array compiles
|
320
388
|
# according to <tt>:filter_mode</tt> option value
|
321
389
|
#
|
322
|
-
# By default it
|
390
|
+
# By default it joins inside <tt>and</tt> filter
|
323
391
|
# See <tt>#filter_mode</tt> chainable method for more info.
|
324
392
|
#
|
325
393
|
# Also this method supports block DSL.
|
@@ -347,6 +415,37 @@ module Chewy
|
|
347
415
|
chain { criteria.update_filters params }
|
348
416
|
end
|
349
417
|
|
418
|
+
# Adds one or more post_filter to the search request
|
419
|
+
# Internally post_filters are stored as an array
|
420
|
+
# While the full query compilation this array compiles
|
421
|
+
# according to <tt>:post_filter_mode</tt> option value
|
422
|
+
#
|
423
|
+
# By default it joins inside <tt>and</tt> filter
|
424
|
+
# See <tt>#post_filter_mode</tt> chainable method for more info.
|
425
|
+
#
|
426
|
+
# Also this method supports block DSL.
|
427
|
+
# See <tt>Chewy::Query::Filters</tt> for more info.
|
428
|
+
#
|
429
|
+
# UsersIndex.post_filter(term: {name: 'Johny'}).post_filter(range: {age: {lte: 42}})
|
430
|
+
# UsersIndex::User.post_filter(term: {name: 'Johny'}).post_filter(range: {age: {lte: 42}})
|
431
|
+
# UsersIndex.post_filter{ name == 'Johny' }.post_filter{ age <= 42 }
|
432
|
+
# # => {body: {
|
433
|
+
# post_filter: {and: [{term: {name: 'Johny'}}, {range: {age: {lte: 42}}}]}
|
434
|
+
# }}
|
435
|
+
#
|
436
|
+
# If only one post_filter was specified, it will become a result
|
437
|
+
# post_filter as is, without joining.
|
438
|
+
#
|
439
|
+
# UsersIndex.post_filter(term: {name: 'Johny'})
|
440
|
+
# # => {body: {
|
441
|
+
# post_filter: {term: {name: 'Johny'}}
|
442
|
+
# }}
|
443
|
+
#
|
444
|
+
def post_filter params = nil, &block
|
445
|
+
params = Filters.new(&block).__render__ if block
|
446
|
+
chain { criteria.update_post_filters params }
|
447
|
+
end
|
448
|
+
|
350
449
|
# Sets search request sorting
|
351
450
|
#
|
352
451
|
# UsersIndex.order(:first_name, :last_name).order(age: :desc).order(price: {order: :asc, mode: :avg})
|
@@ -474,7 +573,7 @@ module Chewy
|
|
474
573
|
end
|
475
574
|
|
476
575
|
def reset
|
477
|
-
@_request, @_response, @_results = nil
|
576
|
+
@_request, @_response, @_results, @_collection = nil
|
478
577
|
end
|
479
578
|
|
480
579
|
def _request
|
@@ -484,17 +583,32 @@ module Chewy
|
|
484
583
|
def _response
|
485
584
|
@_response ||= begin
|
486
585
|
ActiveSupport::Notifications.instrument 'search_query.chewy', request: _request, index: index do
|
487
|
-
|
586
|
+
begin
|
587
|
+
index.client.search(_request)
|
588
|
+
rescue Elasticsearch::Transport::Transport::Errors::NotFound => e
|
589
|
+
raise e if e.message !~ /IndexMissingException/
|
590
|
+
{}
|
591
|
+
end
|
488
592
|
end
|
489
593
|
end
|
490
594
|
end
|
491
595
|
|
492
596
|
def _results
|
493
|
-
@_results ||= (criteria.none? ? [] : _response['hits']['hits']).map do |hit|
|
494
|
-
attributes = hit['_source'] || {}
|
495
|
-
attributes.reverse_merge!(id: hit['_id'])
|
496
|
-
|
497
|
-
index.type_hash[hit['_type']].new attributes
|
597
|
+
@_results ||= (criteria.none? || _response == {} ? [] : _response['hits']['hits']).map do |hit|
|
598
|
+
attributes = (hit['_source'] || {}).merge(hit['highlight'] || {}, &RESULT_MERGER)
|
599
|
+
attributes.reverse_merge!(id: hit['_id']).merge!(_score: hit['_score'])
|
600
|
+
|
601
|
+
wrapper = index.type_hash[hit['_type']].new attributes
|
602
|
+
wrapper._data = hit
|
603
|
+
wrapper
|
604
|
+
end
|
605
|
+
end
|
606
|
+
|
607
|
+
def _collection
|
608
|
+
@_collection ||= begin
|
609
|
+
_load_objects! if criteria.options[:preload]
|
610
|
+
criteria.options[:preload] && criteria.options[:loaded_objects] ?
|
611
|
+
_results.map(&:_object) : _results
|
498
612
|
end
|
499
613
|
end
|
500
614
|
end
|
data/lib/chewy/query/compose.rb
CHANGED
@@ -4,16 +4,26 @@ module Chewy
|
|
4
4
|
|
5
5
|
protected
|
6
6
|
|
7
|
-
def
|
8
|
-
if
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
7
|
+
def _filtered_query query, filter, options = {}
|
8
|
+
query = { match_all: {} } if !query.present? && filter.present?
|
9
|
+
|
10
|
+
if filter.present?
|
11
|
+
filtered = if query.present?
|
12
|
+
{ query: { filtered: {
|
13
|
+
query: query,
|
14
|
+
filter: filter
|
15
|
+
} } }
|
16
|
+
else
|
17
|
+
{ query: { filtered: {
|
18
|
+
filter: filter
|
19
|
+
} } }
|
20
|
+
end
|
21
|
+
filtered[:query][:filtered].merge!(strategy: options[:strategy].to_s) if options[:strategy].present?
|
22
|
+
filtered
|
23
|
+
elsif query.present?
|
24
|
+
{ query: query }
|
25
|
+
else
|
26
|
+
{ }
|
17
27
|
end
|
18
28
|
end
|
19
29
|
|
@@ -23,14 +33,14 @@ module Chewy
|
|
23
33
|
if queries.many?
|
24
34
|
case logic
|
25
35
|
when :dis_max
|
26
|
-
{dis_max: {queries: queries}}
|
36
|
+
{ dis_max: { queries: queries } }
|
27
37
|
when :must, :should
|
28
|
-
{bool: {logic => queries}}
|
38
|
+
{ bool: { logic => queries } }
|
29
39
|
else
|
30
40
|
if logic.is_a?(Float)
|
31
|
-
{dis_max: {queries: queries, tie_breaker: logic}}
|
41
|
+
{ dis_max: { queries: queries, tie_breaker: logic } }
|
32
42
|
else
|
33
|
-
{bool: {should: queries, minimum_should_match: logic}}
|
43
|
+
{ bool: { should: queries, minimum_should_match: logic } }
|
34
44
|
end
|
35
45
|
end
|
36
46
|
else
|
@@ -44,11 +54,11 @@ module Chewy
|
|
44
54
|
if filters.many?
|
45
55
|
case logic
|
46
56
|
when :and, :or
|
47
|
-
{logic => filters}
|
57
|
+
{ logic => filters }
|
48
58
|
when :must, :should
|
49
|
-
{bool: {logic => filters}}
|
59
|
+
{ bool: { logic => filters } }
|
50
60
|
else
|
51
|
-
{bool: {should: filters, minimum_should_match: logic}}
|
61
|
+
{ bool: { should: filters, minimum_should_match: logic } }
|
52
62
|
end
|
53
63
|
else
|
54
64
|
filters.first
|
data/lib/chewy/query/criteria.rb
CHANGED
@@ -4,12 +4,16 @@ module Chewy
|
|
4
4
|
class Query
|
5
5
|
class Criteria
|
6
6
|
include Compose
|
7
|
-
ARRAY_STORAGES = [:queries, :filters, :sort, :fields, :types]
|
8
|
-
HASH_STORAGES = [:options, :facets, :aggregations]
|
7
|
+
ARRAY_STORAGES = [:queries, :filters, :post_filters, :sort, :fields, :types]
|
8
|
+
HASH_STORAGES = [:options, :request_options, :facets, :aggregations, :suggest]
|
9
9
|
STORAGES = ARRAY_STORAGES + HASH_STORAGES
|
10
10
|
|
11
11
|
def initialize options = {}
|
12
|
-
@options = options.merge(
|
12
|
+
@options = options.merge(
|
13
|
+
query_mode: Chewy.query_mode,
|
14
|
+
filter_mode: Chewy.filter_mode,
|
15
|
+
post_filter_mode: Chewy.filter_mode || Chewy.post_filter_mode
|
16
|
+
)
|
13
17
|
end
|
14
18
|
|
15
19
|
def == other
|
@@ -40,6 +44,10 @@ module Chewy
|
|
40
44
|
options.merge!(modifer)
|
41
45
|
end
|
42
46
|
|
47
|
+
def update_request_options(modifer)
|
48
|
+
request_options.merge!(modifer)
|
49
|
+
end
|
50
|
+
|
43
51
|
def update_facets(modifer)
|
44
52
|
facets.merge!(modifer)
|
45
53
|
end
|
@@ -48,12 +56,16 @@ module Chewy
|
|
48
56
|
aggregations.merge!(modifer)
|
49
57
|
end
|
50
58
|
|
51
|
-
def
|
52
|
-
|
59
|
+
def update_suggest(modifier)
|
60
|
+
suggest.merge!(modifier)
|
53
61
|
end
|
54
62
|
|
55
|
-
|
56
|
-
|
63
|
+
[:filters, :queries, :post_filters].each do |storage|
|
64
|
+
class_eval <<-RUBY
|
65
|
+
def update_#{storage}(modifer)
|
66
|
+
@#{storage} = #{storage} + Array.wrap(modifer).reject(&:blank?)
|
67
|
+
end
|
68
|
+
RUBY
|
57
69
|
end
|
58
70
|
|
59
71
|
def update_sort(modifer, options = {})
|
@@ -85,14 +97,17 @@ module Chewy
|
|
85
97
|
end
|
86
98
|
|
87
99
|
def request_body
|
88
|
-
body =
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
100
|
+
body = {}
|
101
|
+
|
102
|
+
body.merge!(_filtered_query(_request_query, _request_filter, options.slice(:strategy)))
|
103
|
+
body.merge!(post_filter: _request_post_filter) if post_filters?
|
104
|
+
body.merge!(facets: facets) if facets?
|
105
|
+
body.merge!(aggregations: aggregations) if aggregations?
|
106
|
+
body.merge!(suggest: suggest) if suggest?
|
107
|
+
body.merge!(sort: sort) if sort?
|
108
|
+
body.merge!(_source: fields) if fields?
|
94
109
|
|
95
|
-
{body: body.merge!(
|
110
|
+
{ body: body.merge!(request_options) }
|
96
111
|
end
|
97
112
|
|
98
113
|
protected
|
@@ -104,17 +119,10 @@ module Chewy
|
|
104
119
|
def initialize_clone(other)
|
105
120
|
STORAGES.each do |storage|
|
106
121
|
value = other.send(storage)
|
107
|
-
|
108
|
-
value = Marshal.load(Marshal.dump(value))
|
109
|
-
instance_variable_set("@#{storage}", value)
|
110
|
-
end
|
122
|
+
instance_variable_set("@#{storage}", value.deep_dup)
|
111
123
|
end
|
112
124
|
end
|
113
125
|
|
114
|
-
def _request_options
|
115
|
-
options.slice(:size, :from, :explain, :aggregations)
|
116
|
-
end
|
117
|
-
|
118
126
|
def _request_query
|
119
127
|
_queries_join(queries, options[:query_mode])
|
120
128
|
end
|
@@ -133,6 +141,10 @@ module Chewy
|
|
133
141
|
def _request_types
|
134
142
|
_filters_join(types.map { |type| {type: {value: type}} }, :or)
|
135
143
|
end
|
144
|
+
|
145
|
+
def _request_post_filter
|
146
|
+
_filters_join(post_filters, options[:post_filter_mode])
|
147
|
+
end
|
136
148
|
end
|
137
149
|
end
|
138
150
|
end
|