search_flip 3.0.0.beta2 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8594c0c22592c2dfa8fb54097151a87db3746221586b8c28e4c6c3c5c02dff6c
4
- data.tar.gz: 55b27e4f8e3bc04c4420280d1dccafbf66e5f7e53cf6914c16f5e5dd3cb5ae10
3
+ metadata.gz: fa160794662cedbe89066113cb845c84daaee29451ba8c8ba4f9183689b42582
4
+ data.tar.gz: b55133b0f4f90f61db0b76042c1223a17035f277ba221a00c0f665512e1cb170
5
5
  SHA512:
6
- metadata.gz: d54c4c22ba4637573d590288cf1a2407d0ff066e9c4505e3ee851a431ff6ebdc318424ea3af63b2c4d426f74521e27a1800c361feb97dec37c7d1159328dc819
7
- data.tar.gz: 1b1bd5e46c5edfc2f1c7d3674564b1bb5627956aee05e16d06e1bdbf1107a70cdd1114bc530cb380db40cc16f383481bafc573c63e1ac3e26b218df97f0d65ed
6
+ metadata.gz: eb2e1e1fd39d64639b9a1f542997e6a00c6238226144fbd32f45f0023f93aa827a1c54597fb71f993090c9d78bcb8b92bbac3a5185d584f26cbeb2e1c4b1a641
7
+ data.tar.gz: caea53f0332131113662b24818268bfd5e3cf537ad04b07b853aba600fc4edd417d1783fd3a1d37fd6d848a75df21ec2e3d39c45a8dafab5fdc515d6f8ca43a9
@@ -1,3 +1,6 @@
1
+ AllCops:
2
+ NewCops: enable
3
+
1
4
  Style/HashTransformValues:
2
5
  Enabled: false
3
6
 
@@ -5,9 +5,11 @@ env:
5
5
  - ES_IMAGE=elasticsearch:5.4
6
6
  - ES_IMAGE=docker.elastic.co/elasticsearch/elasticsearch:6.7.0
7
7
  - ES_IMAGE=docker.elastic.co/elasticsearch/elasticsearch:7.0.0
8
- - ES_IMAGE=docker.elastic.co/elasticsearch/elasticsearch:7.4.0
8
+ - ES_IMAGE=docker.elastic.co/elasticsearch/elasticsearch:7.6.0
9
9
  rvm:
10
+ - ruby-2.5.3
10
11
  - ruby-2.6.2
12
+ - ruby-2.7.1
11
13
  before_install:
12
14
  - docker-compose up -d
13
15
  - sleep 10
@@ -21,6 +21,13 @@
21
21
  * `Connection#freeze_index`, `Connection#unfreeze_index`, `Index#freeze_index`
22
22
  and `Index#unfreeze_index` added
23
23
  * Added `SearchFlip::Result.from_hit`
24
+ * Added support for `source`, `sort`, `page`, `per`, `paginate`, `explain`, and
25
+ `highlight` to aggregations
26
+ * Added support for instrumentation
27
+
28
+ ## v2.3.2
29
+
30
+ * Remove ruby 2.7 warnings
24
31
 
25
32
  ## v2.3.1
26
33
 
data/README.md CHANGED
@@ -274,7 +274,7 @@ CommentIndex.create(Comment.first, { bulk_max_mb: 100 }, routing: "routing_key")
274
274
  CommentIndex.update(Comment.first, ...)
275
275
  ```
276
276
 
277
- Checkout the elasticsearch [Bulk API] docs for more info as well as
277
+ Checkout the Elasticsearch [Bulk API] docs for more info as well as
278
278
  [SearchFlip::Bulk](http://www.rubydoc.info/github/mrkamel/search_flip/SearchFlip/Bulk)
279
279
  for a complete list of available options to control the bulk indexing of
280
280
  SearchFlip.
@@ -505,6 +505,14 @@ end
505
505
  query.aggregations(:average_price).average_price.value
506
506
  ```
507
507
 
508
+ Even various criteria for top hits aggregations can be specified elegantly:
509
+
510
+ ```ruby
511
+ query = ProductIndex.aggregate(sponsored: { top_hits: {} }) do |aggregation|
512
+ aggregation.sort(:rank).highlight(:title).source([:id, :title])
513
+ end
514
+ ```
515
+
508
516
  Checkout [Aggregatable](http://www.rubydoc.info/github/mrkamel/search_flip/SearchFlip/Aggregatable)
509
517
  as well as [Aggregation](http://www.rubydoc.info/github/mrkamel/search_flip/SearchFlip/Aggregation)
510
518
  for a complete API reference.
@@ -782,6 +790,30 @@ end
782
790
 
783
791
  These options will be passed whenever records get indexed, deleted, etc.
784
792
 
793
+ ## Instrumentation
794
+
795
+ SearchFlip supports instrumentation for request execution via
796
+ `ActiveSupport::Notifications` compatible instrumenters to e.g. allow global
797
+ performance tracing, etc.
798
+
799
+ To use instrumentation, configure the instrumenter:
800
+
801
+ ```ruby
802
+ SearchFlip::Config[:instrumenter] = ActiveSupport::Notifications.notifier
803
+ ```
804
+
805
+ Subsequently, you can subscribe to notifcations for `request.search_flip`:
806
+
807
+ ```ruby
808
+ ActiveSupport::Notifications.subscribe("request.search_flip") do |name, start, finish, id, payload|
809
+ payload[:index] # the index class
810
+ payload[:request] # the request hash sent to Elasticsearch
811
+ payload[:response] # the SearchFlip::Response object or nil in case of errors
812
+ end
813
+ ```
814
+
815
+ A notification will be send for every request that is sent to Elasticsearch.
816
+
785
817
  ## Non-ActiveRecord models
786
818
 
787
819
  SearchFlip ships with built-in support for ActiveRecord models, but using
@@ -1,3 +1,4 @@
1
+ require "ruby2_keywords"
1
2
  require "forwardable"
2
3
  require "http"
3
4
  require "hashie"
@@ -6,6 +7,7 @@ require "oj"
6
7
  require "set"
7
8
 
8
9
  require "search_flip/version"
10
+ require "search_flip/null_instrumenter"
9
11
  require "search_flip/helper"
10
12
  require "search_flip/exceptions"
11
13
  require "search_flip/json"
@@ -14,6 +16,12 @@ require "search_flip/config"
14
16
  require "search_flip/connection"
15
17
  require "search_flip/bulk"
16
18
  require "search_flip/filterable"
19
+ require "search_flip/customable"
20
+ require "search_flip/explainable"
21
+ require "search_flip/highlightable"
22
+ require "search_flip/paginatable"
23
+ require "search_flip/sortable"
24
+ require "search_flip/sourceable"
17
25
  require "search_flip/post_filterable"
18
26
  require "search_flip/aggregatable"
19
27
  require "search_flip/aggregation"
@@ -57,7 +57,15 @@ module SearchFlip
57
57
  if block
58
58
  aggregation = yield(SearchFlip::Aggregation.new(target: target))
59
59
 
60
- field_or_hash.is_a?(Hash) ? hash[field_or_hash.keys.first].merge!(aggregation.to_hash) : hash[field_or_hash].merge!(aggregation.to_hash)
60
+ if field_or_hash.is_a?(Hash)
61
+ aggregation_hash = field_or_hash.values.first
62
+ aggregation_hash = aggregation_hash[:top_hits] if aggregation_hash.is_a?(Hash) && aggregation_hash.key?(:top_hits)
63
+ aggregation_hash = aggregation_hash["top_hits"] if aggregation_hash.is_a?(Hash) && aggregation_hash.key?("top_hits")
64
+
65
+ aggregation_hash.merge!(aggregation.to_hash)
66
+ else
67
+ hash[field_or_hash].merge!(aggregation.to_hash)
68
+ end
61
69
  end
62
70
 
63
71
  criteria.aggregation_values = (aggregation_values || {}).merge(hash)
@@ -6,6 +6,12 @@ module SearchFlip
6
6
  class Aggregation
7
7
  include Filterable
8
8
  include Aggregatable
9
+ include Paginatable
10
+ include Highlightable
11
+ include Explainable
12
+ include Sourceable
13
+ include Sortable
14
+ include Customable
9
15
 
10
16
  attr_reader :target
11
17
 
@@ -40,6 +46,15 @@ module SearchFlip
40
46
  end
41
47
  end
42
48
 
49
+ res.update(from: offset_value_with_default, size: limit_value_with_default) if offset_value || limit_value
50
+
51
+ res[:explain] = explain_value unless explain_value.nil?
52
+ res[:highlight] = highlight_values if highlight_values
53
+ res[:sort] = sort_values if sort_values
54
+ res[:_source] = source_value unless source_value.nil?
55
+
56
+ res.update(custom_value) if custom_value
57
+
43
58
  res
44
59
  end
45
60
 
@@ -56,11 +71,10 @@ module SearchFlip
56
71
 
57
72
  fresh.tap do |aggregation|
58
73
  unsupported_methods = [
59
- :profile_value, :failsafe_value, :terminate_after_value, :timeout_value, :offset_value, :limit_value,
60
- :scroll_args, :highlight_values, :suggest_values, :custom_value, :source_value, :sort_values,
61
- :includes_values, :preload_values, :eager_load_values, :post_must_values,
62
- :post_must_not_values, :post_filter_values, :preference_value,
63
- :search_type_value, :routing_value
74
+ :profile_value, :failsafe_value, :terminate_after_value, :timeout_value, :scroll_args,
75
+ :suggest_values, :includes_values, :preload_values, :eager_load_values, :post_must_values,
76
+ :post_must_not_values, :post_filter_values, :preference_value, :search_type_value,
77
+ :routing_value
64
78
  ]
65
79
 
66
80
  unsupported_methods.each do |unsupported_method|
@@ -69,10 +83,19 @@ module SearchFlip
69
83
  end
70
84
  end
71
85
 
86
+ aggregation.source_value = other.source_value if other.source_value
87
+ aggregation.offset_value = other.offset_value if other.offset_value
88
+ aggregation.limit_value = other.limit_value if other.limit_value
89
+ aggregation.scroll_args = other.scroll_args if other.scroll_args
90
+ aggregation.explain_value = other.explain_value unless other.explain_value.nil?
91
+
92
+ aggregation.sort_values = (aggregation.sort_values || []) + other.sort_values if other.sort_values
72
93
  aggregation.must_values = (aggregation.must_values || []) + other.must_values if other.must_values
73
94
  aggregation.must_not_values = (aggregation.must_not_values || []) + other.must_not_values if other.must_not_values
74
95
  aggregation.filter_values = (aggregation.filter_values || []) + other.filter_values if other.filter_values
75
96
 
97
+ aggregation.highlight_values = (aggregation.highlight_values || {}).merge(other.highlight_values) if other.highlight_values
98
+ aggregation.custom_value = (aggregation.custom_value || {}).merge(other.custom_value) if other.custom_value
76
99
  aggregation.aggregation_values = (aggregation.aggregation_values || {}).merge(other.aggregation_values) if other.aggregation_values
77
100
  end
78
101
  end
@@ -89,6 +112,8 @@ module SearchFlip
89
112
  end
90
113
  end
91
114
 
115
+ ruby2_keywords :method_missing
116
+
92
117
  # @api private
93
118
  #
94
119
  # Simply dups the object for api compatability.
@@ -77,7 +77,7 @@ module SearchFlip
77
77
  # and versioning
78
78
 
79
79
  def index(id, object, options = {})
80
- perform :index, id, SearchFlip::JSON.generate(object), options
80
+ perform(:index, id, SearchFlip::JSON.generate(object), options)
81
81
  end
82
82
 
83
83
  # @api private
@@ -86,7 +86,7 @@ module SearchFlip
86
86
  #
87
87
  # @see #index
88
88
 
89
- def import(*args)
89
+ ruby2_keywords def import(*args)
90
90
  index(*args)
91
91
  end
92
92
 
@@ -100,7 +100,7 @@ module SearchFlip
100
100
  # and versioning
101
101
 
102
102
  def create(id, object, options = {})
103
- perform :create, id, SearchFlip::JSON.generate(object), options
103
+ perform(:create, id, SearchFlip::JSON.generate(object), options)
104
104
  end
105
105
 
106
106
  # @api private
@@ -113,7 +113,7 @@ module SearchFlip
113
113
  # and versioning
114
114
 
115
115
  def update(id, object, options = {})
116
- perform :update, id, SearchFlip::JSON.generate(object), options
116
+ perform(:update, id, SearchFlip::JSON.generate(object), options)
117
117
  end
118
118
 
119
119
  # @api private
@@ -125,7 +125,7 @@ module SearchFlip
125
125
  # and versioning
126
126
 
127
127
  def delete(id, options = {})
128
- perform :delete, id, nil, options
128
+ perform(:delete, id, nil, options)
129
129
  end
130
130
 
131
131
  private
@@ -4,6 +4,7 @@ module SearchFlip
4
4
  base_url: "http://127.0.0.1:9200",
5
5
  bulk_limit: 1_000,
6
6
  bulk_max_mb: 100,
7
- auto_refresh: false
7
+ auto_refresh: false,
8
+ instrumenter: NullInstrumenter.new
8
9
  }
9
10
  end
@@ -13,15 +13,20 @@ module SearchFlip
13
13
  # CommentIndex.sort("_doc").find_each { |comment| "..." }
14
14
 
15
15
  class Criteria
16
+ include Sortable
17
+ include Sourceable
18
+ include Highlightable
19
+ include Explainable
20
+ include Paginatable
21
+ include Customable
16
22
  include Filterable
17
23
  include PostFilterable
18
24
  include Aggregatable
19
25
  extend Forwardable
20
26
 
21
- attr_accessor :target, :profile_value, :source_value, :sort_values, :highlight_values, :suggest_values,
22
- :offset_value, :limit_value, :includes_values, :eager_load_values, :preload_values, :failsafe_value,
23
- :scroll_args, :custom_value, :terminate_after_value, :timeout_value, :preference_value, :search_type_value,
24
- :routing_value, :track_total_hits_value, :explain_value
27
+ attr_accessor :target, :profile_value, :source_value, :suggest_values, :includes_values,
28
+ :eager_load_values, :preload_values, :failsafe_value, :scroll_args, :terminate_after_value,
29
+ :timeout_value, :preference_value, :search_type_value, :routing_value, :track_total_hits_value
25
30
 
26
31
  # Creates a new criteria while merging the attributes (constraints,
27
32
  # settings, etc) of the current criteria with the attributes of another one
@@ -71,22 +76,6 @@ module SearchFlip
71
76
  end
72
77
  end
73
78
 
74
- # Specifies whether or not to enable explanation for each hit on how
75
- # its score was computed.
76
- #
77
- # @example
78
- # CommentIndex.explain(true)
79
- #
80
- # @param value [Boolean] The value for explain
81
- #
82
- # @return [SearchFlip::Criteria] A newly created extended criteria
83
-
84
- def explain(value)
85
- fresh.tap do |criteria|
86
- criteria.explain_value = value
87
- end
88
- end
89
-
90
79
  # Specifies if or how many hits should be counted/tracked. Check out the
91
80
  # elasticsearch docs for futher details.
92
81
  #
@@ -217,7 +206,7 @@ module SearchFlip
217
206
  #
218
207
  # @return [SearchFlip::Criteria] Simply returns self
219
208
 
220
- def with_settings(*args)
209
+ ruby2_keywords def with_settings(*args)
221
210
  fresh.tap do |criteria|
222
211
  criteria.target = target.with_settings(*args)
223
212
  end
@@ -230,81 +219,46 @@ module SearchFlip
230
219
  # @return [Hash] The generated request object
231
220
 
232
221
  def request
233
- res = {}
234
-
235
- if must_values || must_not_values || filter_values
236
- res[:query] = {
237
- bool: {
238
- must: must_values.to_a,
239
- must_not: must_not_values.to_a,
240
- filter: filter_values.to_a
241
- }.reject { |_, value| value.empty? }
242
- }
243
- end
244
-
245
- res.update(from: offset_value_with_default, size: limit_value_with_default)
246
-
247
- res[:track_total_hits] = track_total_hits_value unless track_total_hits_value.nil?
248
- res[:explain] = explain_value unless explain_value.nil?
249
- res[:timeout] = timeout_value if timeout_value
250
- res[:terminate_after] = terminate_after_value if terminate_after_value
251
- res[:highlight] = highlight_values if highlight_values
252
- res[:suggest] = suggest_values if suggest_values
253
- res[:sort] = sort_values if sort_values
254
- res[:aggregations] = aggregation_values if aggregation_values
255
-
256
- if post_must_values || post_must_not_values || post_filter_values
257
- res[:post_filter] = {
258
- bool: {
259
- must: post_must_values.to_a,
260
- must_not: post_must_not_values.to_a,
261
- filter: post_filter_values.to_a
262
- }.reject { |_, value| value.empty? }
263
- }
264
- end
265
-
266
- res[:_source] = source_value unless source_value.nil?
267
- res[:profile] = true if profile_value
222
+ @request ||= begin
223
+ res = {}
224
+
225
+ if must_values || must_not_values || filter_values
226
+ res[:query] = {
227
+ bool: {
228
+ must: must_values.to_a,
229
+ must_not: must_not_values.to_a,
230
+ filter: filter_values.to_a
231
+ }.reject { |_, value| value.empty? }
232
+ }
233
+ end
268
234
 
269
- res.update(custom_value) if custom_value
235
+ res.update(from: offset_value_with_default, size: limit_value_with_default)
236
+
237
+ res[:track_total_hits] = track_total_hits_value unless track_total_hits_value.nil?
238
+ res[:explain] = explain_value unless explain_value.nil?
239
+ res[:timeout] = timeout_value if timeout_value
240
+ res[:terminate_after] = terminate_after_value if terminate_after_value
241
+ res[:highlight] = highlight_values if highlight_values
242
+ res[:suggest] = suggest_values if suggest_values
243
+ res[:sort] = sort_values if sort_values
244
+ res[:aggregations] = aggregation_values if aggregation_values
245
+
246
+ if post_must_values || post_must_not_values || post_filter_values
247
+ res[:post_filter] = {
248
+ bool: {
249
+ must: post_must_values.to_a,
250
+ must_not: post_must_not_values.to_a,
251
+ filter: post_filter_values.to_a
252
+ }.reject { |_, value| value.empty? }
253
+ }
254
+ end
270
255
 
271
- res
272
- end
256
+ res[:_source] = source_value unless source_value.nil?
257
+ res[:profile] = true if profile_value
273
258
 
274
- # Adds highlighting of the given fields to the request.
275
- #
276
- # @example
277
- # CommentIndex.highlight([:title, :message])
278
- # CommentIndex.highlight(:title).highlight(:description)
279
- # CommentIndex.highlight(:title, require_field_match: false)
280
- # CommentIndex.highlight(title: { type: "fvh" })
281
- #
282
- # @example
283
- # query = CommentIndex.highlight(:title).search("hello")
284
- # query.results[0].highlight.title # => "<em>hello</em> world"
285
- #
286
- # @param fields [Hash, Array, String, Symbol] The fields to highligt.
287
- # Supports raw Elasticsearch values by passing a Hash.
288
- #
289
- # @param options [Hash] Extra highlighting options. Check out the Elasticsearch
290
- # docs for further details.
291
- #
292
- # @return [SearchFlip::Criteria] A new criteria including the highlighting
259
+ res.update(custom_value) if custom_value
293
260
 
294
- def highlight(fields, options = {})
295
- fresh.tap do |criteria|
296
- criteria.highlight_values = (criteria.highlight_values || {}).merge(options)
297
-
298
- hash =
299
- if fields.is_a?(Hash)
300
- fields
301
- elsif fields.is_a?(Array)
302
- fields.each_with_object({}) { |field, h| h[field] = {} }
303
- else
304
- { fields => {} }
305
- end
306
-
307
- criteria.highlight_values[:fields] = (criteria.highlight_values[:fields] || {}).merge(hash)
261
+ res
308
262
  end
309
263
  end
310
264
 
@@ -397,24 +351,6 @@ module SearchFlip
397
351
  true
398
352
  end
399
353
 
400
- # Use to specify which fields of the source document you want Elasticsearch
401
- # to return for each matching result.
402
- #
403
- # @example
404
- # CommentIndex.source([:id, :message]).search("hello world")
405
- # CommentIndex.source(exclude: "description")
406
- # CommentIndex.source(false)
407
- #
408
- # @param value Pass any allowed value to restrict the returned source
409
- #
410
- # @return [SearchFlip::Criteria] A newly created extended criteria
411
-
412
- def source(value)
413
- fresh.tap do |criteria|
414
- criteria.source_value = value
415
- end
416
- end
417
-
418
354
  # Specify associations of the target model you want to include via
419
355
  # ActiveRecord's or other ORM's mechanisms when records get fetched from
420
356
  # the database.
@@ -472,166 +408,6 @@ module SearchFlip
472
408
  end
473
409
  end
474
410
 
475
- # Specify the sort order you want Elasticsearch to use for sorting the
476
- # results. When you call this multiple times, the sort orders are appended
477
- # to the already existing ones. The sort arguments get passed to
478
- # Elasticsearch without modifications, such that you can use sort by
479
- # script, etc here as well.
480
- #
481
- # @example Default usage
482
- # CommentIndex.sort(:user_id, :id)
483
- #
484
- # # Same as
485
- #
486
- # CommentIndex.sort(:user_id).sort(:id)
487
- #
488
- # @example Default hash usage
489
- # CommentIndex.sort(user_id: "asc").sort(id: "desc")
490
- #
491
- # # Same as
492
- #
493
- # CommentIndex.sort({ user_id: "asc" }, { id: "desc" })
494
- #
495
- # @example Sort by native script
496
- # CommentIndex.sort("_script" => "sort_script", lang: "native", order: "asc", type: "number")
497
- #
498
- # @param args The sort values that get passed to Elasticsearch
499
- #
500
- # @return [SearchFlip::Criteria] A newly created extended criteria
501
-
502
- def sort(*args)
503
- fresh.tap do |criteria|
504
- criteria.sort_values = (sort_values || []) + args
505
- end
506
- end
507
-
508
- alias_method :order, :sort
509
-
510
- # Specify the sort order you want Elasticsearch to use for sorting the
511
- # results with already existing sort orders being removed.
512
- #
513
- # @example
514
- # CommentIndex.sort(user_id: "asc").resort(id: "desc")
515
- #
516
- # # Same as
517
- #
518
- # CommentIndex.sort(id: "desc")
519
- #
520
- # @return [SearchFlip::Criteria] A newly created extended criteria
521
- #
522
- # @see #sort See #sort for more details
523
-
524
- def resort(*args)
525
- fresh.tap do |criteria|
526
- criteria.sort_values = args
527
- end
528
- end
529
-
530
- alias_method :reorder, :resort
531
-
532
- # Adds a fully custom field/section to the request, such that upcoming or
533
- # minor Elasticsearch features as well as other custom requirements can be
534
- # used without having yet specialized criteria methods.
535
- #
536
- # @note Use with caution, because using #custom will potentiall override
537
- # other sections like +aggregations+, +query+, +sort+, etc if you use the
538
- # the same section names.
539
- #
540
- # @example
541
- # CommentIndex.custom(section: { argument: "value" }).request
542
- # => {:section=>{:argument=>"value"},...}
543
- #
544
- # @param hash [Hash] The custom section that is added to the request
545
- #
546
- # @return [SearchFlip::Criteria] A newly created extended criteria
547
-
548
- def custom(hash)
549
- fresh.tap do |criteria|
550
- criteria.custom_value = (custom_value || {}).merge(hash)
551
- end
552
- end
553
-
554
- # Sets the request offset, ie SearchFlip's from parameter that is used
555
- # to skip results in the result set from being returned.
556
- #
557
- # @example
558
- # CommentIndex.offset(100)
559
- #
560
- # @param value [Fixnum] The offset value, ie the number of results that are
561
- # skipped in the result set
562
- #
563
- # @return [SearchFlip::Criteria] A newly created extended criteria
564
-
565
- def offset(value)
566
- fresh.tap do |criteria|
567
- criteria.offset_value = value.to_i
568
- end
569
- end
570
-
571
- # @api private
572
- #
573
- # Returns the offset value or, if not yet set, the default limit value (0).
574
- #
575
- # @return [Fixnum] The offset value
576
-
577
- def offset_value_with_default
578
- (offset_value || 0).to_i
579
- end
580
-
581
- # Sets the request limit, ie Elasticsearch's size parameter that is used
582
- # to restrict the results that get returned.
583
- #
584
- # @example
585
- # CommentIndex.limit(100)
586
- #
587
- # @param value [Fixnum] The limit value, ie the max number of results that
588
- # should be returned
589
- #
590
- # @return [SearchFlip::Criteria] A newly created extended criteria
591
-
592
- def limit(value)
593
- fresh.tap do |criteria|
594
- criteria.limit_value = value.to_i
595
- end
596
- end
597
-
598
- # @api private
599
- #
600
- # Returns the limit value or, if not yet set, the default limit value (30).
601
- #
602
- # @return [Fixnum] The limit value
603
-
604
- def limit_value_with_default
605
- (limit_value || 30).to_i
606
- end
607
-
608
- # Sets pagination parameters for the criteria by using offset and limit,
609
- # ie Elasticsearch's from and size parameters.
610
- #
611
- # @example
612
- # CommentIndex.paginate(page: 3)
613
- # CommentIndex.paginate(page: 5, per_page: 60)
614
- #
615
- # @param page [#to_i] The current page
616
- # @param per_page [#to_i] The number of results per page
617
- #
618
- # @return [SearchFlip::Criteria] A newly created extended criteria
619
-
620
- def paginate(page: 1, per_page: 30)
621
- page = [page.to_i, 1].max
622
- per_page = per_page.to_i
623
-
624
- offset((page - 1) * per_page).limit(per_page)
625
- end
626
-
627
- def page(value)
628
- paginate(page: value, per_page: limit_value_with_default)
629
- end
630
-
631
- def per(value)
632
- paginate(page: 1 + (offset_value_with_default / limit_value_with_default), per_page: value)
633
- end
634
-
635
411
  # Fetches the records specified by the criteria in batches using the
636
412
  # ElasicSearch scroll API and yields each batch. The batch size and scroll
637
413
  # API timeout can be specified. Check out the Elasticsearch docs for
@@ -746,30 +522,13 @@ module SearchFlip
746
522
 
747
523
  def execute
748
524
  @response ||= begin
749
- http_request = connection.http_client.headers(accept: "application/json")
750
-
751
- http_response =
752
- if scroll_args && scroll_args[:id]
753
- http_request.post(
754
- "#{connection.base_url}/_search/scroll",
755
- params: request_params,
756
- json: { scroll: scroll_args[:timeout], scroll_id: scroll_args[:id] }
757
- )
758
- elsif scroll_args
759
- http_request.post(
760
- "#{target.type_url}/_search",
761
- params: request_params.merge(scroll: scroll_args[:timeout]),
762
- json: request
763
- )
764
- else
765
- http_request.post("#{target.type_url}/_search", params: request_params, json: request)
766
- end
767
-
768
- SearchFlip::Response.new(self, http_response.parse)
769
- rescue SearchFlip::ConnectionError, SearchFlip::ResponseError => e
770
- raise e unless failsafe_value
771
-
772
- SearchFlip::Response.new(self, "took" => 0, "hits" => { "total" => 0, "hits" => [] })
525
+ Config[:instrumenter].instrument("request.search_flip", index: target, request: request) do |payload|
526
+ response = execute!
527
+
528
+ payload[:response] = response
529
+
530
+ response
531
+ end
773
532
  end
774
533
  end
775
534
 
@@ -811,6 +570,7 @@ module SearchFlip
811
570
 
812
571
  def fresh
813
572
  dup.tap do |criteria|
573
+ criteria.instance_variable_set(:@request, nil)
814
574
  criteria.instance_variable_set(:@response, nil)
815
575
  end
816
576
  end
@@ -827,6 +587,8 @@ module SearchFlip
827
587
  end
828
588
  end
829
589
 
590
+ ruby2_keywords :method_missing
591
+
830
592
  def_delegators :response, :total_entries, :total_count, :current_page, :previous_page,
831
593
  :prev_page, :next_page, :first_page?, :last_page?, :out_of_range?, :total_pages,
832
594
  :hits, :ids, :count, :size, :length, :took, :aggregations, :suggestions,
@@ -836,6 +598,33 @@ module SearchFlip
836
598
 
837
599
  private
838
600
 
601
+ def execute!
602
+ http_request = connection.http_client.headers(accept: "application/json")
603
+
604
+ http_response =
605
+ if scroll_args && scroll_args[:id]
606
+ http_request.post(
607
+ "#{connection.base_url}/_search/scroll",
608
+ params: request_params,
609
+ json: { scroll: scroll_args[:timeout], scroll_id: scroll_args[:id] }
610
+ )
611
+ elsif scroll_args
612
+ http_request.post(
613
+ "#{target.type_url}/_search",
614
+ params: request_params.merge(scroll: scroll_args[:timeout]),
615
+ json: request
616
+ )
617
+ else
618
+ http_request.post("#{target.type_url}/_search", params: request_params, json: request)
619
+ end
620
+
621
+ SearchFlip::Response.new(self, http_response.parse)
622
+ rescue SearchFlip::ConnectionError, SearchFlip::ResponseError => e
623
+ raise e unless failsafe_value
624
+
625
+ SearchFlip::Response.new(self, "took" => 0, "hits" => { "total" => 0, "hits" => [] })
626
+ end
627
+
839
628
  def yield_in_batches(options = {})
840
629
  return enum_for(:yield_in_batches, options) unless block_given?
841
630