search_flip 3.0.0.beta2 → 3.0.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 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