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