couchbase 3.4.0-arm64-darwin-20

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.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +202 -0
  3. data/README.md +154 -0
  4. data/ext/extconf.rb +0 -0
  5. data/lib/active_support/cache/couchbase_store.rb +339 -0
  6. data/lib/couchbase/analytics_options.rb +107 -0
  7. data/lib/couchbase/authenticator.rb +65 -0
  8. data/lib/couchbase/binary_collection.rb +128 -0
  9. data/lib/couchbase/binary_collection_options.rb +24 -0
  10. data/lib/couchbase/bucket.rb +144 -0
  11. data/lib/couchbase/cluster.rb +439 -0
  12. data/lib/couchbase/cluster_registry.rb +44 -0
  13. data/lib/couchbase/collection.rb +589 -0
  14. data/lib/couchbase/collection_options.rb +300 -0
  15. data/lib/couchbase/config_profiles.rb +55 -0
  16. data/lib/couchbase/configuration.rb +57 -0
  17. data/lib/couchbase/datastructures/couchbase_list.rb +160 -0
  18. data/lib/couchbase/datastructures/couchbase_map.rb +194 -0
  19. data/lib/couchbase/datastructures/couchbase_queue.rb +134 -0
  20. data/lib/couchbase/datastructures/couchbase_set.rb +128 -0
  21. data/lib/couchbase/datastructures.rb +24 -0
  22. data/lib/couchbase/diagnostics.rb +181 -0
  23. data/lib/couchbase/errors.rb +351 -0
  24. data/lib/couchbase/json_transcoder.rb +32 -0
  25. data/lib/couchbase/libcouchbase.bundle +0 -0
  26. data/lib/couchbase/logger.rb +85 -0
  27. data/lib/couchbase/management/analytics_index_manager.rb +1127 -0
  28. data/lib/couchbase/management/bucket_manager.rb +436 -0
  29. data/lib/couchbase/management/collection_manager.rb +321 -0
  30. data/lib/couchbase/management/query_index_manager.rb +520 -0
  31. data/lib/couchbase/management/search_index_manager.rb +408 -0
  32. data/lib/couchbase/management/user_manager.rb +468 -0
  33. data/lib/couchbase/management/view_index_manager.rb +237 -0
  34. data/lib/couchbase/management.rb +27 -0
  35. data/lib/couchbase/mutation_state.rb +63 -0
  36. data/lib/couchbase/options.rb +2580 -0
  37. data/lib/couchbase/query_options.rb +120 -0
  38. data/lib/couchbase/railtie.rb +45 -0
  39. data/lib/couchbase/scope.rb +232 -0
  40. data/lib/couchbase/search_options.rb +1570 -0
  41. data/lib/couchbase/subdoc.rb +290 -0
  42. data/lib/couchbase/utils/generic_logger_adapter.rb +38 -0
  43. data/lib/couchbase/utils/stdlib_logger_adapter.rb +65 -0
  44. data/lib/couchbase/utils/time.rb +56 -0
  45. data/lib/couchbase/utils.rb +21 -0
  46. data/lib/couchbase/version.rb +23 -0
  47. data/lib/couchbase/view_options.rb +65 -0
  48. data/lib/couchbase.rb +20 -0
  49. data/lib/rails/generators/couchbase/config/config_generator.rb +27 -0
  50. metadata +101 -0
@@ -0,0 +1,1570 @@
1
+ # Copyright 2020-2021 Couchbase, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Couchbase
16
+ class Cluster
17
+ class SearchQuery
18
+ # Prepare {MatchQuery} body
19
+ #
20
+ # @param [String] match
21
+ # @yieldparam [MatchQuery] query
22
+ #
23
+ # @return [MatchQuery]
24
+ def self.match(match, &block)
25
+ MatchQuery.new(match, &block)
26
+ end
27
+
28
+ # A match query analyzes the input text and uses that analyzed text to query the index.
29
+ class MatchQuery < SearchQuery
30
+ # @return [Float]
31
+ attr_accessor :boost
32
+
33
+ # @return [String]
34
+ attr_accessor :field
35
+
36
+ # @return [String]
37
+ attr_accessor :analyzer
38
+
39
+ # @return [Integer]
40
+ attr_accessor :prefix_length
41
+
42
+ # @return [Integer]
43
+ attr_accessor :fuzziness
44
+
45
+ # @return [nil, :or, :and]
46
+ attr_accessor :operator
47
+
48
+ # @param [String] match
49
+ # @yieldparam [MatchQuery] self
50
+ def initialize(match)
51
+ super()
52
+ @match = match
53
+ yield self if block_given?
54
+ end
55
+
56
+ # @return [String]
57
+ def to_json(*args)
58
+ data = {"match" => @match}
59
+ data["boost"] = boost if boost
60
+ data["field"] = field if field
61
+ data["analyzer"] = analyzer if analyzer
62
+ if fuzziness
63
+ data["fuzziness"] = fuzziness
64
+ data["prefix_length"] = prefix_length if prefix_length
65
+ end
66
+ data.to_json(*args)
67
+ end
68
+ end
69
+
70
+ # Prepare {MatchPhraseQuery} body
71
+ #
72
+ # @param [String] match_phrase
73
+ # @yieldparam [MatchPhraseQuery] query
74
+ #
75
+ # @return [MatchPhraseQuery]
76
+ def self.match_phrase(match_phrase, &block)
77
+ MatchPhraseQuery.new(match_phrase, &block)
78
+ end
79
+
80
+ # The input text is analyzed and a phrase query is built with the terms resulting from the analysis.
81
+ class MatchPhraseQuery < SearchQuery
82
+ # @return [Float]
83
+ attr_accessor :boost
84
+
85
+ # @return [nil, :or, :and]
86
+ attr_accessor :operator
87
+
88
+ # @return [String]
89
+ attr_accessor :field
90
+
91
+ # @return [String]
92
+ attr_accessor :analyzer
93
+
94
+ # @param [String] match_phrase
95
+ #
96
+ # @yieldparam [MatchPhraseQuery] self
97
+ def initialize(match_phrase)
98
+ super()
99
+ @match_phrase = match_phrase
100
+ yield self if block_given?
101
+ end
102
+
103
+ # @return [String]
104
+ def to_json(*args)
105
+ data = {"match_phrase" => @match_phrase}
106
+ data["boost"] = boost if boost
107
+ data["operator"] = operator.to_s if operator
108
+ data["field"] = field if field
109
+ data["analyzer"] = analyzer if analyzer
110
+ data.to_json(*args)
111
+ end
112
+ end
113
+
114
+ # Prepare {RegexpQuery} body
115
+ #
116
+ # @param [String] regexp
117
+ # @yieldparam [RegexpQuery] query
118
+ #
119
+ # @return [RegexpQuery]
120
+ def self.regexp(regexp, &block)
121
+ RegexpQuery.new(regexp, &block)
122
+ end
123
+
124
+ # Finds documents containing terms that match the specified regular expression.
125
+ class RegexpQuery < SearchQuery
126
+ # @return [Float]
127
+ attr_accessor :boost
128
+
129
+ # @return [nil, :or, :and]
130
+ attr_accessor :operator
131
+
132
+ # @return [String]
133
+ attr_accessor :field
134
+
135
+ # @param [String] regexp
136
+ #
137
+ # @yieldparam [RegexpQuery] self
138
+ def initialize(regexp)
139
+ super()
140
+ @regexp = regexp
141
+ yield self if block_given?
142
+ end
143
+
144
+ # @return [String]
145
+ def to_json(*args)
146
+ data = {"regexp" => @regexp}
147
+ data["boost"] = boost if boost
148
+ data["operator"] = operator.to_s if operator
149
+ data["field"] = field if field
150
+ data.to_json(*args)
151
+ end
152
+ end
153
+
154
+ # Prepare {QueryStringQuery} body
155
+ #
156
+ # @param [String] query_string
157
+ # @yieldparam [QueryStringQuery] query
158
+ #
159
+ # @return [QueryStringQuery]
160
+ def self.query_string(query_string, &block)
161
+ QueryStringQuery.new(query_string, &block)
162
+ end
163
+
164
+ # The query string query allows humans to describe complex queries using a simple syntax.
165
+ class QueryStringQuery < SearchQuery
166
+ # @return [Float]
167
+ attr_accessor :boost
168
+
169
+ # @return [nil, :or, :and]
170
+ attr_accessor :operator
171
+
172
+ # @param [String] query_string
173
+ #
174
+ # @yieldparam [QueryStringQuery] self
175
+ def initialize(query_string)
176
+ super()
177
+ @query_string = query_string
178
+ yield self if block_given?
179
+ end
180
+
181
+ # @return [String]
182
+ def to_json(*args)
183
+ data = {"query" => @query_string}
184
+ data["boost"] = boost if boost
185
+ data["operator"] = operator.to_s if operator
186
+ data.to_json(*args)
187
+ end
188
+ end
189
+
190
+ # Prepare {WildcardQuery} body
191
+ #
192
+ # @param [String] wildcard
193
+ # @yieldparam [WildcardQuery] query
194
+ #
195
+ # @return [WildcardQuery]
196
+ def self.wildcard(wildcard, &block)
197
+ WildcardQuery.new(wildcard, &block)
198
+ end
199
+
200
+ # Interprets * and ? wildcards as found in a lot of applications, for an easy implementation of such a search feature.
201
+ class WildcardQuery < SearchQuery
202
+ # @return [Float]
203
+ attr_accessor :boost
204
+
205
+ # @return [nil, :or, :and]
206
+ attr_accessor :operator
207
+
208
+ # @return [String]
209
+ attr_accessor :field
210
+
211
+ # @param [String] wildcard
212
+ #
213
+ # @yieldparam [WildcardQuery] self
214
+ def initialize(wildcard)
215
+ super()
216
+ @wildcard = wildcard
217
+ yield self if block_given?
218
+ end
219
+
220
+ # @return [String]
221
+ def to_json(*args)
222
+ data = {"wildcard" => @wildcard}
223
+ data["boost"] = boost if boost
224
+ data["operator"] = operator.to_s if operator
225
+ data["field"] = field if field
226
+ data.to_json(*args)
227
+ end
228
+ end
229
+
230
+ # Prepare {DocIdQuery} body
231
+ #
232
+ # @param [String...] doc_ids
233
+ # @yieldparam [DocIdQuery] query
234
+ #
235
+ # @return [DocIdQuery]
236
+ def self.doc_id(*doc_ids)
237
+ DocIdQuery.new(*doc_ids)
238
+ end
239
+
240
+ # Allows to restrict matches to a set of specific documents.
241
+ class DocIdQuery < SearchQuery
242
+ # @return [Float]
243
+ attr_accessor :boost
244
+
245
+ # @return [nil, :or, :and]
246
+ attr_accessor :operator
247
+
248
+ # @return [String]
249
+ attr_accessor :field
250
+
251
+ # @param [String...] doc_ids
252
+ #
253
+ # @yieldparam [DocIdQuery] self
254
+ def initialize(*doc_ids)
255
+ super()
256
+ @doc_ids = doc_ids
257
+ yield self if block_given?
258
+ end
259
+
260
+ # @return [String]
261
+ def to_json(*args)
262
+ data = {"doc_ids" => @doc_ids.flatten.uniq}
263
+ data["boost"] = boost if boost
264
+ data["operator"] = operator.to_s if operator
265
+ data["field"] = field if field
266
+ data.to_json(*args)
267
+ end
268
+ end
269
+
270
+ # Prepare {BooleanFieldQuery} body
271
+ #
272
+ # @param [Boolean] value
273
+ # @yieldparam [BooleanFieldQuery] query
274
+ #
275
+ # @return [BooleanFieldQuery]
276
+ def self.boolean_field(value)
277
+ BooleanFieldQuery.new(value)
278
+ end
279
+
280
+ # Allow to match `true`/`false` in a field mapped as boolean.
281
+ class BooleanFieldQuery < SearchQuery
282
+ # @return [Float]
283
+ attr_accessor :boost
284
+
285
+ # @return [nil, :or, :and]
286
+ attr_accessor :operator
287
+
288
+ # @return [String]
289
+ attr_accessor :field
290
+
291
+ # @param [Boolean] value
292
+ #
293
+ # @yieldparam [BooleanFieldQuery] self
294
+ def initialize(value)
295
+ super()
296
+ @value = value
297
+ yield self if block_given?
298
+ end
299
+
300
+ # @return [String]
301
+ def to_json(*args)
302
+ data = {"bool" => @value}
303
+ data["boost"] = boost if boost
304
+ data["operator"] = operator.to_s if operator
305
+ data["field"] = field if field
306
+ data.to_json(*args)
307
+ end
308
+ end
309
+
310
+ # Prepare {DateRangeQuery} body
311
+ #
312
+ # @yieldparam [DateRangeQuery] query
313
+ #
314
+ # @return [DateRangeQuery]
315
+ def self.date_range(&block)
316
+ DateRangeQuery.new(&block)
317
+ end
318
+
319
+ # The date range query finds documents containing a date value in the specified field within the specified range.
320
+ class DateRangeQuery < SearchQuery
321
+ # @return [Float]
322
+ attr_accessor :boost
323
+
324
+ # @return [nil, :or, :and]
325
+ attr_accessor :operator
326
+
327
+ # @return [String]
328
+ attr_accessor :field
329
+
330
+ # @return [String]
331
+ attr_accessor :date_time_parser
332
+
333
+ # Sets the lower boundary of the range.
334
+ #
335
+ # @note The lower boundary is considered inclusive by default on the server side.
336
+ #
337
+ # @param [Time, String] time_point start time. When +Time+ object is passed {#date_time_parser} must be +nil+ (to use server
338
+ # default)
339
+ # @param [Boolean] inclusive
340
+ def start_time(time_point, inclusive = nil)
341
+ @start_time = time_point
342
+ @start_inclusive = inclusive
343
+ end
344
+
345
+ # Sets the upper boundary of the range.
346
+ #
347
+ # @note The upper boundary is considered exclusive by default on the server side.
348
+ #
349
+ # @param [Time, String] time_point end time. When +Time+ object is passed {#date_time_parser} must be +nil+ (to use server default)
350
+ # @param [Boolean] inclusive
351
+ def end_time(time_point, inclusive = nil)
352
+ @end_time = time_point
353
+ @end_inclusive = inclusive
354
+ end
355
+
356
+ # @yieldparam [DateRangeQuery] self
357
+ def initialize
358
+ super
359
+ @start_time = nil
360
+ @start_inclusive = nil
361
+ @end_time = nil
362
+ @end_inclusive = nil
363
+ yield self if block_given?
364
+ end
365
+
366
+ DATE_FORMAT_RFC3339 = "%Y-%m-%dT%H:%M:%S%:z".freeze
367
+
368
+ # @return [String]
369
+ def to_json(*args)
370
+ raise ArgumentError, "either start_time or end_time must be set for DateRangeQuery" if @start_time.nil? && @end_time.nil?
371
+
372
+ data = {}
373
+ data["boost"] = boost if boost
374
+ data["operator"] = operator.to_s if operator
375
+ data["field"] = field if field
376
+ data["datetime_parser"] = date_time_parser if date_time_parser
377
+ if @start_time
378
+ data["start"] = if @start_time.respond_to?(:strftime)
379
+ @start_time.strftime(DATE_FORMAT_RFC3339)
380
+ else
381
+ @start_time
382
+ end
383
+ data["inclusive_start"] = @start_inclusive unless @start_inclusive.nil?
384
+ end
385
+ if @end_time
386
+ data["end"] = if @end_time.respond_to?(:strftime)
387
+ @end_time.strftime(DATE_FORMAT_RFC3339)
388
+ else
389
+ @end_time
390
+ end
391
+ data["inclusive_end"] = @end_inclusive unless @end_inclusive.nil?
392
+ end
393
+ data.to_json(*args)
394
+ end
395
+ end
396
+
397
+ # Prepare {NumericRangeQuery} body
398
+ #
399
+ # @yieldparam [NumericRangeQuery] query
400
+ #
401
+ # @return [NumericRangeQuery]
402
+ def self.numeric_range(&block)
403
+ NumericRangeQuery.new(&block)
404
+ end
405
+
406
+ # The numeric range query finds documents containing a numeric value in the specified field within the specified range.
407
+ class NumericRangeQuery < SearchQuery
408
+ # @return [Float]
409
+ attr_accessor :boost
410
+
411
+ # @return [nil, :or, :and]
412
+ attr_accessor :operator
413
+
414
+ # @return [String]
415
+ attr_accessor :field
416
+
417
+ # Sets lower bound of the range.
418
+ #
419
+ # The lower boundary is considered inclusive by default on the server side.
420
+ #
421
+ # @param [Numeric] lower_bound
422
+ # @param [Boolean] inclusive
423
+ def min(lower_bound, inclusive = nil)
424
+ @min = lower_bound
425
+ @min_inclusive = inclusive
426
+ end
427
+
428
+ # Sets upper bound of the range.
429
+ #
430
+ # The upper boundary is considered exclusive by default on the server side.
431
+ #
432
+ # @param [Numeric] upper_bound
433
+ # @param [Boolean] inclusive
434
+ def max(upper_bound, inclusive = nil)
435
+ @max = upper_bound
436
+ @max_inclusive = inclusive
437
+ end
438
+
439
+ # @yieldparam [NumericRangeQuery] self
440
+ def initialize
441
+ super
442
+ @min = nil
443
+ @min_inclusive = nil
444
+ @max = nil
445
+ @max_inclusive = nil
446
+ yield self if block_given?
447
+ end
448
+
449
+ # @return [String]
450
+ def to_json(*args)
451
+ raise ArgumentError, "either min or max must be set for NumericRangeQuery" if @min.nil? && @max.nil?
452
+
453
+ data = {}
454
+ data["boost"] = boost if boost
455
+ data["operator"] = operator.to_s if operator
456
+ data["field"] = field if field
457
+ if @min
458
+ data["min"] = @min
459
+ data["inclusive_min"] = @min_inclusive unless @min_inclusive.nil?
460
+ end
461
+ if @max
462
+ data["max"] = @max
463
+ data["inclusive_max"] = @max_inclusive unless @max_inclusive.nil?
464
+ end
465
+ data.to_json(*args)
466
+ end
467
+ end
468
+
469
+ # Prepare {TermRangeQuery} body
470
+ #
471
+ # @yieldparam [TermRangeQuery] query
472
+ #
473
+ # @return [TermRangeQuery]
474
+ def self.term_range(&block)
475
+ TermRangeQuery.new(&block)
476
+ end
477
+
478
+ # The term range query finds documents containing a string value in the specified field within the specified range.
479
+ class TermRangeQuery < SearchQuery
480
+ # @return [Float]
481
+ attr_accessor :boost
482
+
483
+ # @return [nil, :or, :and]
484
+ attr_accessor :operator
485
+
486
+ # @return [String]
487
+ attr_accessor :field
488
+
489
+ # Sets lower bound of the range.
490
+ #
491
+ # The lower boundary is considered inclusive by default on the server side.
492
+ #
493
+ # @param [String] lower_bound
494
+ # @param [Boolean] inclusive
495
+ def min(lower_bound, inclusive = nil)
496
+ @min = lower_bound
497
+ @min_inclusive = inclusive
498
+ end
499
+
500
+ # Sets upper bound of the range.
501
+ #
502
+ # The upper boundary is considered exclusive by default on the server side.
503
+ #
504
+ # @param [String] upper_bound
505
+ # @param [Boolean] inclusive
506
+ def max(upper_bound, inclusive = nil)
507
+ @max = upper_bound
508
+ @max_inclusive = inclusive
509
+ end
510
+
511
+ # @yieldparam [TermRangeQuery] self
512
+ def initialize
513
+ super
514
+ @min = nil
515
+ @min_inclusive = nil
516
+ @max = nil
517
+ @max_inclusive = nil
518
+ yield self if block_given?
519
+ end
520
+
521
+ # @return [String]
522
+ def to_json(*args)
523
+ raise ArgumentError, "either min or max must be set for TermRangeQuery" if @min.nil? && @max.nil?
524
+
525
+ data = {}
526
+ data["boost"] = boost if boost
527
+ data["operator"] = operator.to_s if operator
528
+ data["field"] = field if field
529
+ if @min
530
+ data["min"] = @min
531
+ data["inclusive_min"] = @min_inclusive unless @min_inclusive.nil?
532
+ end
533
+ if @max
534
+ data["max"] = @max
535
+ data["inclusive_max"] = @max_inclusive unless @max_inclusive.nil?
536
+ end
537
+ data.to_json(*args)
538
+ end
539
+ end
540
+
541
+ # Prepare {GeoDistanceQuery} body
542
+ #
543
+ # @yieldparam [GeoDistanceQuery] query
544
+ #
545
+ # @param [Float] latitude location latitude
546
+ # @param [Float] longitude location longitude
547
+ # @param [String] distance how big is area (number with units)
548
+ #
549
+ # @return [GeoDistanceQuery]
550
+ def self.geo_distance(longitude, latitude, distance, &block)
551
+ GeoDistanceQuery.new(longitude, latitude, distance, &block)
552
+ end
553
+
554
+ # Finds `geopoint` indexed matches around a point with the given distance.
555
+ class GeoDistanceQuery < SearchQuery
556
+ # @return [Float]
557
+ attr_accessor :boost
558
+
559
+ # @return [nil, :or, :and]
560
+ attr_accessor :operator
561
+
562
+ # @return [String]
563
+ attr_accessor :field
564
+
565
+ # @yieldparam [GeoDistanceQuery] self
566
+ # @param [Float] longitude
567
+ # @param [Float] latitude
568
+ # @param [Float] distance
569
+ def initialize(longitude, latitude, distance)
570
+ super()
571
+ @longitude = longitude
572
+ @latitude = latitude
573
+ @distance = distance
574
+ yield self if block_given?
575
+ end
576
+
577
+ # @return [String]
578
+ def to_json(*args)
579
+ data = {
580
+ "location" => [@longitude, @latitude],
581
+ "distance" => @distance,
582
+ }
583
+ data["boost"] = boost if boost
584
+ data["operator"] = operator.to_s if operator
585
+ data["field"] = field if field
586
+ data.to_json(*args)
587
+ end
588
+ end
589
+
590
+ # Prepare {GeoBoundingBoxQuery} body
591
+ #
592
+ # @yieldparam [GeoBoundingBoxQuery] query
593
+ #
594
+ # @param [Float] top_left_longitude
595
+ # @param [Float] top_left_latitude
596
+ # @param [Float] bottom_right_longitude
597
+ # @param [Float] bottom_right_latitude
598
+ #
599
+ # @return [GeoBoundingBoxQuery]
600
+ def self.geo_bounding_box(top_left_longitude, top_left_latitude, bottom_right_longitude, bottom_right_latitude, &block)
601
+ GeoBoundingBoxQuery.new(top_left_longitude, top_left_latitude, bottom_right_longitude, bottom_right_latitude, &block)
602
+ end
603
+
604
+ # Finds `geopoint` indexed matches in a given bounding box.
605
+ class GeoBoundingBoxQuery < SearchQuery
606
+ # @return [Float]
607
+ attr_accessor :boost
608
+
609
+ # @return [nil, :or, :and]
610
+ attr_accessor :operator
611
+
612
+ # @return [String]
613
+ attr_accessor :field
614
+
615
+ # @yieldparam [GeoBoundingBoxQuery] self
616
+ #
617
+ # @param [Float] top_left_longitude
618
+ # @param [Float] top_left_latitude
619
+ # @param [Float] bottom_right_longitude
620
+ # @param [Float] bottom_right_latitude
621
+ def initialize(top_left_longitude, top_left_latitude, bottom_right_longitude, bottom_right_latitude)
622
+ super()
623
+ @top_left_longitude = top_left_longitude
624
+ @top_left_latitude = top_left_latitude
625
+ @bottom_right_longitude = bottom_right_longitude
626
+ @bottom_right_latitude = bottom_right_latitude
627
+ yield self if block_given?
628
+ end
629
+
630
+ # @return [String]
631
+ def to_json(*args)
632
+ data = {
633
+ "top_left" => [@top_left_longitude, @top_left_latitude],
634
+ "bottom_right" => [@bottom_right_longitude, @bottom_right_latitude],
635
+ }
636
+ data["boost"] = boost if boost
637
+ data["operator"] = operator.to_s if operator
638
+ data["field"] = field if field
639
+ data.to_json(*args)
640
+ end
641
+ end
642
+
643
+ # A coordinate is a tuple of a latitude and a longitude.
644
+ #
645
+ # @see GeoPolygonQuery
646
+ # @see SearchQuery.geo_polygon
647
+ class Coordinate
648
+ # @return [Float]
649
+ attr_accessor :longitude
650
+
651
+ # @return [Float]
652
+ attr_accessor :latitude
653
+
654
+ def initialize(longitude, latitude)
655
+ @longitude = longitude
656
+ @latitude = latitude
657
+ end
658
+ end
659
+
660
+ # Prepare {GeoPolygonQuery} body
661
+ #
662
+ # @yieldparam [GeoPolygonQuery] query
663
+ #
664
+ # @param [Array<Coordinate>] coordinates list of coordinates that forms polygon
665
+ #
666
+ # @return [GeoPolygonQuery]
667
+ #
668
+ # @api uncommitted
669
+ def self.geo_polygon(coordinates, &block)
670
+ GeoPolygonQuery.new(coordinates, &block)
671
+ end
672
+
673
+ # A search query which allows to match inside a geo polygon.
674
+ class GeoPolygonQuery < SearchQuery
675
+ # @return [Float]
676
+ attr_accessor :boost
677
+
678
+ # @return [nil, :or, :and]
679
+ attr_accessor :operator
680
+
681
+ # @return [String]
682
+ attr_accessor :field
683
+
684
+ # @yieldparam [GeoPolygonQuery] self
685
+ #
686
+ # @param [Array<Coordinate>] coordinates list of coordinates that forms polygon
687
+ def initialize(coordinates)
688
+ super()
689
+ @coordinates = coordinates
690
+ yield self if block_given?
691
+ end
692
+
693
+ # @return [String]
694
+ def to_json(*args)
695
+ data = {
696
+ "polygon_points" => @coordinates.map { |coord| [coord.longitude, coord.latitude] },
697
+ }
698
+ data["boost"] = boost if boost
699
+ data["operator"] = operator.to_s if operator
700
+ data["field"] = field if field
701
+ data.to_json(*args)
702
+ end
703
+ end
704
+
705
+ # Prepare {ConjunctionQuery} body
706
+ #
707
+ # @yieldparam [ConjunctionQuery] query
708
+ #
709
+ # @return [ConjunctionQuery]
710
+ def self.conjuncts(...)
711
+ ConjunctionQuery.new(...)
712
+ end
713
+
714
+ # Result documents must satisfy all of the child queries.
715
+ class ConjunctionQuery < SearchQuery
716
+ # @return [Float]
717
+ attr_accessor :boost
718
+
719
+ # @return [nil, :or, :and]
720
+ attr_accessor :operator
721
+
722
+ # @yieldparam [ConjunctionQuery] self
723
+ #
724
+ # @param [*SearchQuery] queries
725
+ def initialize(*queries)
726
+ super()
727
+ @queries = queries.flatten
728
+ yield self if block_given?
729
+ end
730
+
731
+ # @param [*SearchQuery] queries
732
+ def and_also(*queries)
733
+ @queries |= queries.flatten
734
+ end
735
+
736
+ def empty?
737
+ @queries.empty?
738
+ end
739
+
740
+ # @return [String]
741
+ def to_json(*args)
742
+ raise ArgumentError, "compound conjunction query must have sub-queries" if @queries.nil? || @queries.empty?
743
+
744
+ data = {"conjuncts" => @queries.uniq}
745
+ data["boost"] = boost if boost
746
+ data["operator"] = operator.to_s if operator
747
+ data.to_json(*args)
748
+ end
749
+ end
750
+
751
+ # Prepare {ConjunctionQuery} body
752
+ #
753
+ # @yieldparam [ConjunctionQuery] query
754
+ #
755
+ # @return [ConjunctionQuery]
756
+ def self.disjuncts(...)
757
+ DisjunctionQuery.new(...)
758
+ end
759
+
760
+ # Result documents must satisfy a configurable min number of child queries.
761
+ class DisjunctionQuery < SearchQuery
762
+ # @return [Float]
763
+ attr_accessor :boost
764
+
765
+ # @return [nil, :or, :and]
766
+ attr_accessor :operator
767
+
768
+ # @return [Integer]
769
+ attr_accessor :min
770
+
771
+ # @yieldparam [DisjunctionQuery] self
772
+ #
773
+ # @param [*SearchQuery] queries
774
+ def initialize(*queries)
775
+ super()
776
+ @queries = queries.flatten
777
+ yield self if block_given?
778
+ end
779
+
780
+ # @param [*SearchQuery] queries
781
+ def or_else(*queries)
782
+ @queries |= queries.flatten
783
+ end
784
+
785
+ def empty?
786
+ @queries.empty?
787
+ end
788
+
789
+ # @return [String]
790
+ def to_json(*args)
791
+ raise ArgumentError, "compound disjunction query must have sub-queries" if @queries.nil? || @queries.empty?
792
+
793
+ data = {"disjuncts" => @queries.uniq}
794
+ if min
795
+ raise ArgumentError, "disjunction query has fewer sub-queries than configured minimum" if @queries.size < min
796
+
797
+ data["min"] = min
798
+ end
799
+ data["boost"] = boost if boost
800
+ data["operator"] = operator.to_s if operator
801
+ data.to_json(*args)
802
+ end
803
+ end
804
+
805
+ # Prepare {BooleanQuery} body
806
+ #
807
+ # @yieldparam [BooleanQuery] query
808
+ #
809
+ # @return [BooleanQuery]
810
+ def self.booleans(&block)
811
+ BooleanQuery.new(&block)
812
+ end
813
+
814
+ # The boolean query is a useful combination of conjunction and disjunction queries.
815
+ class BooleanQuery < SearchQuery
816
+ # @return [Float]
817
+ attr_accessor :boost
818
+
819
+ # @return [nil, :or, :and]
820
+ attr_accessor :operator
821
+
822
+ # @yieldparam [BooleanQuery] self
823
+ def initialize
824
+ super()
825
+ @must = ConjunctionQuery.new
826
+ @must_not = DisjunctionQuery.new
827
+ @should = DisjunctionQuery.new
828
+ yield self if block_given?
829
+ end
830
+
831
+ # @param [Integer] min minimal value for "should" disjunction query
832
+ def should_min(min)
833
+ @should.min = min
834
+ self
835
+ end
836
+
837
+ # @param [*SearchQuery] queries
838
+ def must(*queries)
839
+ @must.and_also(*queries)
840
+ self
841
+ end
842
+
843
+ # @param [*SearchQuery] queries
844
+ def must_not(*queries)
845
+ @must_not.or_else(*queries)
846
+ self
847
+ end
848
+
849
+ # @param [*SearchQuery] queries
850
+ def should(*queries)
851
+ @should.or_else(*queries)
852
+ self
853
+ end
854
+
855
+ # @return [String]
856
+ def to_json(*args)
857
+ if @must.empty? && @must_not.empty? && @should.empty?
858
+ raise ArgumentError, "BooleanQuery must have at least one non-empty sub-query"
859
+ end
860
+
861
+ data = {}
862
+ data["must"] = @must unless @must.empty?
863
+ data["must_not"] = @must_not unless @must_not.empty?
864
+ data["should"] = @should unless @should.empty?
865
+ data["boost"] = boost if boost
866
+ data["operator"] = operator.to_s if operator
867
+ data.to_json(*args)
868
+ end
869
+ end
870
+
871
+ # Prepare {TermQuery} body
872
+ #
873
+ # @yieldparam [TermQuery] query
874
+ # @param [String] term
875
+ #
876
+ # @return [TermQuery]
877
+ def self.term(term, &block)
878
+ TermQuery.new(term, &block)
879
+ end
880
+
881
+ # A query that looks for **exact** matches of the term in the index (no analyzer, no stemming). Useful to check what the actual
882
+ # content of the index is. It can also apply fuzziness on the term. Usual better alternative is `MatchQuery`.
883
+ class TermQuery < SearchQuery
884
+ # @return [Float]
885
+ attr_accessor :boost
886
+
887
+ # @return [nil, :or, :and]
888
+ attr_accessor :operator
889
+
890
+ # @return [String]
891
+ attr_accessor :field
892
+
893
+ # @return [Integer]
894
+ attr_accessor :fuzziness
895
+
896
+ # @return [Integer]
897
+ attr_accessor :prefix_length
898
+
899
+ # @yieldparam [TermQuery] self
900
+ #
901
+ # @param [String] term
902
+ def initialize(term)
903
+ super()
904
+ @term = term
905
+ yield self if block_given?
906
+ end
907
+
908
+ # @return [String]
909
+ def to_json(*args)
910
+ data = {"term" => @term}
911
+ data["boost"] = boost if boost
912
+ data["operator"] = operator.to_s if operator
913
+ data["operator"] = operator.to_s if operator
914
+ data["field"] = field if field
915
+ if fuzziness
916
+ data["fuzziness"] = fuzziness
917
+ data["prefix_length"] = prefix_length if prefix_length
918
+ end
919
+ data.to_json(*args)
920
+ end
921
+ end
922
+
923
+ # Prepare {PrefixQuery} body
924
+ #
925
+ # @yieldparam [PrefixQuery] query
926
+ # @param [String] prefix
927
+ #
928
+ # @return [PrefixQuery]
929
+ def self.prefix(prefix, &block)
930
+ PrefixQuery.new(prefix, &block)
931
+ end
932
+
933
+ # The prefix query finds documents containing terms that start with the provided prefix. Usual better alternative is `MatchQuery`.
934
+ class PrefixQuery < SearchQuery
935
+ # @return [Float]
936
+ attr_accessor :boost
937
+
938
+ # @return [nil, :or, :and]
939
+ attr_accessor :operator
940
+
941
+ # @return [String]
942
+ attr_accessor :field
943
+
944
+ # @yieldparam [PrefixQuery] self
945
+ #
946
+ # @param [String] prefix
947
+ def initialize(prefix)
948
+ super()
949
+ @prefix = prefix
950
+ yield self if block_given?
951
+ end
952
+
953
+ # @return [String]
954
+ def to_json(*args)
955
+ data = {"prefix" => @prefix}
956
+ data["boost"] = boost if boost
957
+ data["operator"] = operator.to_s if operator
958
+ data["field"] = field if field
959
+ data.to_json(*args)
960
+ end
961
+ end
962
+
963
+ # Prepare {PhraseQuery} body
964
+ #
965
+ # Creates a new instances {PhraseQuery} passing all parameters into {PhraseQuery#initialize}.
966
+ #
967
+ # @return [PhraseQuery]
968
+ def self.phrase(...)
969
+ PhraseQuery.new(...)
970
+ end
971
+
972
+ # A query that looks for **exact** match of several terms (in the exact order) in the index. Usual better alternative is
973
+ # {MatchPhraseQuery}.
974
+ class PhraseQuery < SearchQuery
975
+ # @return [Float]
976
+ attr_accessor :boost
977
+
978
+ # @return [nil, :or, :and]
979
+ attr_accessor :operator
980
+
981
+ # @return [String]
982
+ attr_accessor :field
983
+
984
+ # @yieldparam [PhraseQuery] self
985
+ #
986
+ # @param [*String] terms
987
+ def initialize(*terms)
988
+ super()
989
+ @terms = terms.flatten
990
+ yield self if block_given?
991
+ end
992
+
993
+ # @return [String]
994
+ def to_json(*args)
995
+ data = {"terms" => @terms.flatten.uniq}
996
+ data["boost"] = boost if boost
997
+ data["operator"] = operator.to_s if operator
998
+ data["field"] = field if field
999
+ data.to_json(*args)
1000
+ end
1001
+ end
1002
+
1003
+ # Prepare {MatchAllQuery} body
1004
+ #
1005
+ # @yieldparam [MatchAllQuery] query
1006
+ #
1007
+ # @return [MatchAllQuery]
1008
+ def self.match_all(&block)
1009
+ MatchAllQuery.new(&block)
1010
+ end
1011
+
1012
+ # A query that matches all indexed documents.
1013
+ class MatchAllQuery < SearchQuery
1014
+ # @return [Float]
1015
+ attr_accessor :boost
1016
+
1017
+ # @return [nil, :or, :and]
1018
+ attr_accessor :operator
1019
+
1020
+ # @yieldparam [MatchAllQuery] self
1021
+ def initialize
1022
+ super()
1023
+ yield self if block_given?
1024
+ end
1025
+
1026
+ # @return [String]
1027
+ def to_json(*args)
1028
+ data = {"match_all" => nil}
1029
+ data["boost"] = boost if boost
1030
+ data["operator"] = operator.to_s if operator
1031
+ data.to_json(*args)
1032
+ end
1033
+ end
1034
+
1035
+ # Prepare {MatchNoneQuery} body
1036
+ #
1037
+ # @yieldparam [MatchNoneQuery] query
1038
+ #
1039
+ # @return [MatchNoneQuery]
1040
+ def self.match_none(&block)
1041
+ MatchNoneQuery.new(&block)
1042
+ end
1043
+
1044
+ # A query that matches nothing.
1045
+ class MatchNoneQuery < SearchQuery
1046
+ # @return [Float]
1047
+ attr_accessor :boost
1048
+
1049
+ # @return [nil, :or, :and]
1050
+ attr_accessor :operator
1051
+
1052
+ # @yieldparam [MatchNoneQuery] self
1053
+ def initialize
1054
+ super()
1055
+ yield self if block_given?
1056
+ end
1057
+
1058
+ # @return [String]
1059
+ def to_json(*args)
1060
+ data = {"match_none" => nil}
1061
+ data["boost"] = boost if boost
1062
+ data["operator"] = operator.to_s if operator
1063
+ data.to_json(*args)
1064
+ end
1065
+ end
1066
+ end
1067
+
1068
+ class SearchSort
1069
+ # @yieldparam [SearchSortScore]
1070
+ # @return [SearchSortScore]
1071
+ def self.score(&block)
1072
+ SearchSortScore.new(&block)
1073
+ end
1074
+
1075
+ # @yieldparam [SearchSortId]
1076
+ # @return [SearchSortScore]
1077
+ def self.id(&block)
1078
+ SearchSortId.new(&block)
1079
+ end
1080
+
1081
+ # @param [String] name field name
1082
+ # @yieldparam [SearchSortField]
1083
+ # @return [SearchSortField]
1084
+ def self.field(name, &block)
1085
+ SearchSortField.new(name, &block)
1086
+ end
1087
+
1088
+ # @param [String] name field name
1089
+ # @param [Float] longitude
1090
+ # @param [Float] latitude
1091
+ # @yieldparam [SearchSortField]
1092
+ # @return [SearchSortGeoDistance]
1093
+ def self.geo_distance(name, longitude, latitude, &block)
1094
+ SearchSortGeoDistance.new(name, longitude, latitude, &block)
1095
+ end
1096
+
1097
+ class SearchSortScore < SearchSort
1098
+ # @return [Boolean] if descending order should be applied
1099
+ attr_accessor :desc
1100
+
1101
+ # @yieldparam [SearchSortScore]
1102
+ def initialize
1103
+ super
1104
+ yield self if block_given?
1105
+ end
1106
+
1107
+ # @api private
1108
+ def to_json(*args)
1109
+ {by: :score, desc: desc}.to_json(*args)
1110
+ end
1111
+ end
1112
+
1113
+ class SearchSortId < SearchSort
1114
+ # @return [Boolean] if descending order should be applied
1115
+ attr_accessor :desc
1116
+
1117
+ # @yieldparam [SearchSortId]
1118
+ def initialize
1119
+ super
1120
+ yield self if block_given?
1121
+ end
1122
+
1123
+ # @api private
1124
+ def to_json(*args)
1125
+ {by: :id, desc: desc}.to_json(*args)
1126
+ end
1127
+ end
1128
+
1129
+ class SearchSortField < SearchSort
1130
+ # @return [String] name of the field to sort by
1131
+ attr_reader :field
1132
+
1133
+ # @return [Boolean] if descending order should be applied
1134
+ attr_accessor :desc
1135
+
1136
+ # @return [:auto, :string, :number, :date]
1137
+ attr_accessor :type
1138
+
1139
+ # @return [:first, :last] where the documents with missing field should be placed
1140
+ attr_accessor :missing
1141
+
1142
+ # @return [:default, :min, :max]
1143
+ attr_accessor :mode
1144
+
1145
+ # @param [String] field the name of the filed for ordering
1146
+ # @yieldparam [SearchSortField]
1147
+ def initialize(field)
1148
+ super()
1149
+ @field = field
1150
+ yield self if block_given?
1151
+ end
1152
+
1153
+ # @api private
1154
+ def to_json(*args)
1155
+ {by: :field, field: field, desc: desc, type: type, missing: missing, mode: mode}.to_json(*args)
1156
+ end
1157
+ end
1158
+
1159
+ class SearchSortGeoDistance < SearchSort
1160
+ # @return [String] name of the field to sort by
1161
+ attr_reader :field
1162
+
1163
+ # @return [Boolean] if descending order should be applied
1164
+ attr_accessor :desc
1165
+
1166
+ # @return [Float]
1167
+ attr_reader :longitude
1168
+
1169
+ # @return [Float]
1170
+ attr_reader :latitude
1171
+
1172
+ # @return [:meters, :miles, :centimeters, :millimeters, :kilometers, :nauticalmiles, :feet, :yards, :inch]
1173
+ attr_accessor :unit
1174
+
1175
+ # @param [String] field field name
1176
+ # @param [Float] longitude
1177
+ # @param [Float] latitude
1178
+ # @yieldparam [SearchSortGeoDistance]
1179
+ def initialize(field, longitude, latitude)
1180
+ super()
1181
+ @field = field
1182
+ @longitude = longitude
1183
+ @latitude = latitude
1184
+ yield self if block_given?
1185
+ end
1186
+
1187
+ # @api private
1188
+ def to_json(*args)
1189
+ {by: :geo_distance, field: field, desc: desc, location: [longitude, latitude], unit: unit}.to_json(*args)
1190
+ end
1191
+ end
1192
+ end
1193
+
1194
+ class SearchFacet
1195
+ # @param [String] field_name
1196
+ # @return [SearchFacetTerm]
1197
+ def self.term(field_name, &block)
1198
+ SearchFacetTerm.new(field_name, &block)
1199
+ end
1200
+
1201
+ # @param [String] field_name
1202
+ # @return [SearchFacetNumericRange]
1203
+ def self.numeric_range(field_name, &block)
1204
+ SearchFacetNumericRange.new(field_name, &block)
1205
+ end
1206
+
1207
+ # @param [String] field_name
1208
+ # @return [SearchFacetDateRange]
1209
+ def self.date_range(field_name, &block)
1210
+ SearchFacetDateRange.new(field_name, &block)
1211
+ end
1212
+
1213
+ class SearchFacetTerm
1214
+ # @return [String]
1215
+ attr_reader :field
1216
+
1217
+ # @return [Integer]
1218
+ attr_accessor :size
1219
+
1220
+ # @param [String] field name of the field
1221
+ def initialize(field)
1222
+ @field = field
1223
+ yield self if block_given?
1224
+ end
1225
+
1226
+ # @api private
1227
+ def to_json(*args)
1228
+ {field: field, size: size}.to_json(*args)
1229
+ end
1230
+ end
1231
+
1232
+ class SearchFacetNumericRange
1233
+ # @return [String]
1234
+ attr_reader :field
1235
+
1236
+ # @return [Integer]
1237
+ attr_accessor :size
1238
+
1239
+ # @param [String] field name of the field
1240
+ def initialize(field)
1241
+ @field = field
1242
+ @ranges = []
1243
+ yield self if block_given?
1244
+ end
1245
+
1246
+ # @param [String] name the name of the range
1247
+ # @param [Integer, Float, nil] min lower bound of the range (pass +nil+ if there is no lower bound)
1248
+ # @param [Integer, Float, nil] max upper bound of the range (pass +nil+ if there is no upper bound)
1249
+ def add(name, min, max)
1250
+ @ranges.append({name: name, min: min, max: max})
1251
+ end
1252
+
1253
+ # @api private
1254
+ def to_json(*args)
1255
+ {field: field, size: size, numeric_ranges: @ranges}.to_json(*args)
1256
+ end
1257
+ end
1258
+
1259
+ class SearchFacetDateRange
1260
+ # @return [String]
1261
+ attr_reader :field
1262
+
1263
+ # @return [Integer]
1264
+ attr_accessor :size
1265
+
1266
+ # @param [String] field name of the field
1267
+ def initialize(field)
1268
+ super()
1269
+ @field = field
1270
+ @ranges = []
1271
+ yield self if block_given?
1272
+ end
1273
+
1274
+ DATE_FORMAT_RFC3339 = "%Y-%m-%dT%H:%M:%S%:z".freeze
1275
+
1276
+ # @param [String] name the name of the range
1277
+ # @param [Time, String, nil] start_time lower bound of the range (pass +nil+ if there is no lower bound)
1278
+ # @param [Time, String, nil] end_time lower bound of the range (pass +nil+ if there is no lower bound)
1279
+ def add(name, start_time, end_time)
1280
+ start_time = start_time.strftime(DATE_FORMAT_RFC3339) if start_time.respond_to?(:strftime)
1281
+ end_time = end_time.strftime(DATE_FORMAT_RFC3339) if end_time.respond_to?(:strftime)
1282
+ @ranges.append({name: name, start: start_time, end: end_time})
1283
+ end
1284
+
1285
+ # @api private
1286
+ def to_json(*args)
1287
+ {field: field, size: size, date_ranges: @ranges}.to_json(*args)
1288
+ end
1289
+ end
1290
+ end
1291
+
1292
+ class SearchRowLocation
1293
+ # @return [String]
1294
+ attr_accessor :field
1295
+
1296
+ # @return [String]
1297
+ attr_accessor :term
1298
+
1299
+ # @return [Integer] the position of the term within the field, starting at 1
1300
+ attr_accessor :position
1301
+
1302
+ # @return [Integer] start byte offset of the term in the field
1303
+ attr_accessor :start_offset
1304
+
1305
+ # @return [Integer] end byte offset of the term in the field
1306
+ attr_accessor :end_offset
1307
+
1308
+ # @return [Array<Integer>] the positions of the term within any elements.
1309
+ attr_accessor :array_positions
1310
+ end
1311
+
1312
+ class SearchRowLocations
1313
+ # Lists all locations (any field, any term)
1314
+ #
1315
+ # @return [Array<SearchRowLocation>]
1316
+ def get_all
1317
+ @locations
1318
+ end
1319
+
1320
+ # Lists all locations for a given field (any term)
1321
+ #
1322
+ # @return [Array<SearchRowLocation>]
1323
+ def get_for_field(name)
1324
+ @locations.select { |location| location.field == name }
1325
+ end
1326
+
1327
+ # Lists all locations for a given field and term
1328
+ #
1329
+ # @return [Array<SearchRowLocation>]
1330
+ def get_for_field_and_term(name, term)
1331
+ @locations.select { |location| location.field == name && location.term == term }
1332
+ end
1333
+
1334
+ # Lists the fields in this location
1335
+ #
1336
+ # @return [Array<String>]
1337
+ def fields
1338
+ @locations.map(&:field).uniq
1339
+ end
1340
+
1341
+ # Lists all terms in this locations, considering all fields
1342
+ #
1343
+ # @return [Array<String>]
1344
+ def terms
1345
+ @locations.map(&:term).uniq
1346
+ end
1347
+
1348
+ # Lists the terms for a given field
1349
+ #
1350
+ # @return [Array<String>]
1351
+ def terms_for_field(name)
1352
+ get_for_field(name).map(&:term).uniq
1353
+ end
1354
+
1355
+ # @param [Array<SearchRowLocation>] locations
1356
+ def initialize(locations)
1357
+ super()
1358
+ @locations = locations
1359
+ end
1360
+ end
1361
+
1362
+ # An individual facet result has both metadata and details, as each facet can define ranges into which results are categorized
1363
+ class SearchFacetResult
1364
+ # @return [String]
1365
+ attr_accessor :name
1366
+
1367
+ # @return [String]
1368
+ attr_accessor :field
1369
+
1370
+ # @return [Integer]
1371
+ attr_accessor :total
1372
+
1373
+ # @return [Integer]
1374
+ attr_accessor :missing
1375
+
1376
+ # @return [Integer]
1377
+ attr_accessor :other
1378
+
1379
+ class TermFacetResult < SearchFacetResult
1380
+ # @return [Array<TermFacet>]
1381
+ attr_accessor :terms
1382
+
1383
+ def type
1384
+ :term_facet
1385
+ end
1386
+
1387
+ # @yieldparam [TermFacetResult] self
1388
+ def initialize
1389
+ super
1390
+ yield self if block_given?
1391
+ end
1392
+
1393
+ class TermFacet
1394
+ # @return [String]
1395
+ attr_reader :term
1396
+
1397
+ # @return [Integer]
1398
+ attr_reader :count
1399
+
1400
+ def initialize(term, count)
1401
+ super()
1402
+ @term = term
1403
+ @count = count
1404
+ end
1405
+ end
1406
+ end
1407
+
1408
+ class DateRangeFacetResult < SearchFacetResult
1409
+ # @return [Array<DateRangeFacet>]
1410
+ attr_accessor :date_ranges
1411
+
1412
+ def type
1413
+ :date_range_facet
1414
+ end
1415
+
1416
+ # @yieldparam [DateRangeFacetResult] self
1417
+ def initialize
1418
+ super
1419
+ yield self if block_given?
1420
+ end
1421
+
1422
+ class DateRangeFacet
1423
+ # @return [String]
1424
+ attr_reader :name
1425
+
1426
+ # @return [Integer]
1427
+ attr_reader :count
1428
+
1429
+ # @return [String]
1430
+ attr_reader :start_time
1431
+
1432
+ # @return [String]
1433
+ attr_reader :end_time
1434
+
1435
+ def initialize(name, count, start_time, end_time)
1436
+ @name = name
1437
+ @count = count
1438
+ @start_time = start_time
1439
+ @end_time = end_time
1440
+ end
1441
+ end
1442
+ end
1443
+
1444
+ class NumericRangeFacetResult < SearchFacetResult
1445
+ # @return [Array<NumericRangeFacet>]
1446
+ attr_accessor :numeric_ranges
1447
+
1448
+ def type
1449
+ :numeric_range_facet
1450
+ end
1451
+
1452
+ # @yieldparam [NumericRangeFacetResult] self
1453
+ def initialize
1454
+ super
1455
+ yield self if block_given?
1456
+ end
1457
+
1458
+ class NumericRangeFacet
1459
+ # @return [String]
1460
+ attr_reader :name
1461
+
1462
+ # @return [Integer]
1463
+ attr_reader :count
1464
+
1465
+ # @return [Integer, Float, nil]
1466
+ attr_reader :min
1467
+
1468
+ # @return [Integer, Float, nil]
1469
+ attr_reader :max
1470
+
1471
+ def initialize(name, count, min, max)
1472
+ @name = name
1473
+ @count = count
1474
+ @min = min
1475
+ @max = max
1476
+ end
1477
+ end
1478
+ end
1479
+ end
1480
+
1481
+ class SearchRow
1482
+ # @return [String] name of the index
1483
+ attr_accessor :index
1484
+
1485
+ # @return [String] document identifier
1486
+ attr_accessor :id
1487
+
1488
+ # @return [Float]
1489
+ attr_accessor :score
1490
+
1491
+ # @return [SearchRowLocations]
1492
+ attr_accessor :locations
1493
+
1494
+ # @return [Hash]
1495
+ attr_accessor :explanation
1496
+
1497
+ # @return [Hash<String => Array<String>>]
1498
+ attr_accessor :fragments
1499
+
1500
+ # @return [JsonTranscoder] transcoder to use for the fields
1501
+ attr_accessor :transcoder
1502
+
1503
+ def fields
1504
+ @transcoder.decode(@fields, :json) if @fields && @transcoder
1505
+ end
1506
+
1507
+ # @yieldparam [SearchRow] self
1508
+ def initialize
1509
+ @fields = nil
1510
+ yield self if block_given?
1511
+ end
1512
+ end
1513
+
1514
+ class SearchMetrics
1515
+ # @return [Integer] time spent executing the query (in milliseconds)
1516
+ attr_accessor :took
1517
+
1518
+ # @return [Integer]
1519
+ attr_accessor :total_rows
1520
+
1521
+ # @return [Float]
1522
+ attr_accessor :max_score
1523
+
1524
+ # @return [Integer]
1525
+ attr_accessor :success_partition_count
1526
+
1527
+ # @return [Integer]
1528
+ attr_accessor :error_partition_count
1529
+
1530
+ # @return [Integer]
1531
+ def total_partition_count
1532
+ success_partition_count + error_partition_count
1533
+ end
1534
+ end
1535
+
1536
+ class SearchMetaData
1537
+ # @return [SearchMetrics]
1538
+ attr_accessor :metrics
1539
+
1540
+ # @return [Hash<String => String>]
1541
+ attr_accessor :errors
1542
+
1543
+ # @yieldparam [SearchMetaData] self
1544
+ def initialize
1545
+ @metrics = SearchMetrics.new
1546
+ yield self if block_given?
1547
+ end
1548
+ end
1549
+
1550
+ class SearchResult
1551
+ # @return [Array<SearchRow>]
1552
+ attr_accessor :rows
1553
+
1554
+ # @return [Hash<String => SearchFacetResult>]
1555
+ attr_accessor :facets
1556
+
1557
+ # @return [SearchMetaData]
1558
+ attr_accessor :meta_data
1559
+
1560
+ def success?
1561
+ meta_data.errors.nil? || meta_data.errors.empty?
1562
+ end
1563
+
1564
+ # @yieldparam [SearchResult] self
1565
+ def initialize
1566
+ yield self if block_given?
1567
+ end
1568
+ end
1569
+ end
1570
+ end