orchestrate 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +138 -10
- data/lib/orchestrate/api/response.rb +4 -0
- data/lib/orchestrate/collection.rb +8 -110
- data/lib/orchestrate/search/aggregate_builder.rb +290 -0
- data/lib/orchestrate/search/query_builder.rb +83 -0
- data/lib/orchestrate/search/results.rb +215 -0
- data/lib/orchestrate/search.rb +10 -0
- data/lib/orchestrate/version.rb +1 -1
- data/lib/orchestrate.rb +1 -0
- data/orchestrate.gemspec +14 -14
- data/test/orchestrate/collection_aggregates_test.rb +118 -0
- data/test/orchestrate/collection_geo_queries_test.rb +5 -5
- data/test/orchestrate/collection_searching_test.rb +9 -10
- data/test/orchestrate/collection_sorting_test.rb +4 -4
- metadata +32 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 052b46ffb077d9256c3626b2d2fe1d6618c0f3c9
|
4
|
+
data.tar.gz: 34375247e7fc3ce08d2f836df6e0df7f778273f7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 99d0edff2baf770cf3c2173c9245bb42957dee1a92c1d4abca2c24bc8b510569bf6bda09159c2761bbd64d9631cdfd1d2273166597dccb11a12f85c1a110fb3d
|
7
|
+
data.tar.gz: 6afa7091564272f7f22d0b4d173b03cd76815a63992876aaccadd3b1c08ab11a38a6c20e884e2feafcf8e339651f0bf0b623339927de6a7e6b1e8c5fd27f39a3
|
data/README.md
CHANGED
@@ -65,20 +65,20 @@ jill.add('favorite_food', 'Pizza').remove('years_to_live').update()
|
|
65
65
|
|
66
66
|
#### Searching, Sorting for KeyValues
|
67
67
|
```ruby
|
68
|
-
users.search("name:Jill")
|
69
|
-
users.search("name:Jill").order(:created_at)
|
68
|
+
users.search("name:Jill").find # returns users with name "Jill"
|
69
|
+
users.search("name:Jill").order(:created_at).find # returns users with name "Jill" in ascending order
|
70
70
|
```
|
71
71
|
|
72
72
|
The `order` method accepts multiple arguments, allowing you to sort search results based multiple parameters. When providing multiple field names to sort by each even-numbered argument must be either `:asc` or `:desc`.
|
73
73
|
|
74
74
|
```ruby
|
75
|
-
users.search("location: Portland").order(:name, :asc, :rank, :desc)
|
75
|
+
users.search("location: Portland").order(:name, :asc, :rank, :desc).find
|
76
76
|
```
|
77
77
|
|
78
78
|
By default, odd-numbered arguments will be sorted in ascending order.
|
79
79
|
```ruby
|
80
|
-
users.search("location: Portland").order(:name)
|
81
|
-
users.search("location: Portland").order(:name, :asc, :rank, :desc, :created_at)
|
80
|
+
users.search("location: Portland").order(:name).find # returns users in ascending order by name
|
81
|
+
users.search("location: Portland").order(:name, :asc, :rank, :desc, :created_at).find # :created_at argument defaults to :asc
|
82
82
|
```
|
83
83
|
|
84
84
|
### Geo Queries
|
@@ -87,13 +87,56 @@ users.search("location: Portland").order(:name, :asc, :rank, :desc, :created_at)
|
|
87
87
|
cafes = app[:cafes]
|
88
88
|
|
89
89
|
# Find cafes near a given geographic point
|
90
|
-
cafes.near(:location, 12.56, 19.443, 4, 'mi') # returns cafes in a 4 mile radius of given latitude, longitude
|
90
|
+
cafes.near(:location, 12.56, 19.443, 4, 'mi').find # returns cafes in a 4 mile radius of given latitude, longitude
|
91
91
|
|
92
92
|
# Sort nearby cafes by distance
|
93
|
-
cafes.near(:location, 12.56, 19.443, 4, 'mi').order(:distance) # returns nearby cafes in ascending order (closest to farthest)
|
93
|
+
cafes.near(:location, 12.56, 19.443, 4, 'mi').order(:distance).find # returns nearby cafes in ascending order (closest to farthest)
|
94
94
|
|
95
95
|
# Find cafes in a given area using a bounding box
|
96
|
-
cafes.in(:location, {north:12.5, east:57, south:12, west:56}) # returns all cafes within specified bounding box
|
96
|
+
cafes.in(:location, {north:12.5, east:57, south:12, west:56}).find # returns all cafes within specified bounding box
|
97
|
+
```
|
98
|
+
|
99
|
+
### Aggregate Functions
|
100
|
+
|
101
|
+
```ruby
|
102
|
+
# Statistical Aggregate
|
103
|
+
products.search("*").aggregate # Start the search query and aggregate param builder
|
104
|
+
.stats("price") # statistics on the price field for products matching the query
|
105
|
+
.find # return SearchResults object to execute our query
|
106
|
+
.each_aggregate # return enumerator for iterating over each aggregate result
|
107
|
+
|
108
|
+
# Range Aggregate
|
109
|
+
products.search("*").aggregate # Start the search query and aggregate param builder
|
110
|
+
.range("num_sold") # set field for range function
|
111
|
+
.below(99) # count items with num_sold value below 99
|
112
|
+
.between(1, 10) # count items with num_sold value between 1 & 10
|
113
|
+
.above(5) # count items with num_sold value above 5
|
114
|
+
.find # return SearchResults object to execute our query
|
115
|
+
.each_aggregate # return enumerator for iterating over each aggregate result
|
116
|
+
|
117
|
+
# Distance Aggregate
|
118
|
+
cafes.near(:location, 12, 19, 4, 'mi').aggregate # Start the near search query and aggregate param builder
|
119
|
+
.distance("location") # set field for distance function
|
120
|
+
.below(3) # count cafes within 3 miles of given geographic point
|
121
|
+
.between(3, 4) # count cafes between 3 and 4 miles of given geographic point
|
122
|
+
.above(1) # count cafes beyond 1 mile of given geographic point
|
123
|
+
.find # return SearchResults object to execute our query
|
124
|
+
.each_aggregate # return enumerator for iterating over each aggregate result
|
125
|
+
|
126
|
+
# Time-Series Aggregate
|
127
|
+
# Accepted intervals are: year, quarter, month, week, day, and hour
|
128
|
+
comments.search("*").aggregate # Start the near search query and aggregate param builder
|
129
|
+
.time_series("posted", "day") # get count of comments posted by day
|
130
|
+
.find # return SearchResults object to execute our query
|
131
|
+
.each_aggregate # return enumerator for iterating over each aggregate result
|
132
|
+
|
133
|
+
# Multiple Aggregate Functions
|
134
|
+
products.search("*").aggregate # Start the search query and aggregate param builder
|
135
|
+
.stats("price") # statistics on the price field for products matching the query
|
136
|
+
.range("num_sold") # set field for range function
|
137
|
+
.below(99) # count items with num_sold value below 99
|
138
|
+
.find # return SearchResults object to execute our query
|
139
|
+
.each_aggregate # return enumerator for iterating over each aggregate result
|
97
140
|
```
|
98
141
|
|
99
142
|
### Method Client use
|
@@ -173,6 +216,82 @@ query = "value:IN:{ north:12.5 east:57 south:12 west:56 }"
|
|
173
216
|
client.search(:cafes, query)
|
174
217
|
```
|
175
218
|
|
219
|
+
### Aggregate Functions
|
220
|
+
|
221
|
+
```ruby
|
222
|
+
# Statistical Aggregate
|
223
|
+
query = "*"
|
224
|
+
|
225
|
+
options = {
|
226
|
+
aggregate: "value.price:stats" # get statistics for price across all items in the collection
|
227
|
+
}
|
228
|
+
|
229
|
+
response = client.search(:products, query, options)
|
230
|
+
|
231
|
+
response.aggregates # return aggregate results
|
232
|
+
|
233
|
+
|
234
|
+
# Range Aggregate
|
235
|
+
query = "*"
|
236
|
+
|
237
|
+
options = {
|
238
|
+
# count items with num_sold below 99, in between 1 & 10, and above 5
|
239
|
+
aggregate: "value.num_sold:range:*~99:1~10:5~*"
|
240
|
+
}
|
241
|
+
|
242
|
+
response = client.search(:products, query, options)
|
243
|
+
|
244
|
+
response.aggregates # return aggregate results
|
245
|
+
|
246
|
+
|
247
|
+
# Distance Aggregate
|
248
|
+
coords = {
|
249
|
+
lat: 12.56,
|
250
|
+
lon: 19.443,
|
251
|
+
dist: '4mi' # Define size of search radius for NEAR query
|
252
|
+
}
|
253
|
+
|
254
|
+
options = {
|
255
|
+
# count cafes near give geographic point within 3 miles, between 3 and 4 miles, and beyond 1 mile
|
256
|
+
aggregate: "value.location:distance:*~3:3~4:1~*"
|
257
|
+
}
|
258
|
+
|
259
|
+
# Distance Aggregates require a near clause in the search query
|
260
|
+
query = "value.location:NEAR:{lat:#{coords.lat} lon:#{coords.lon} dist:#{coords.dist}}"
|
261
|
+
|
262
|
+
response = client.search(:cafes, query, options)
|
263
|
+
|
264
|
+
response.aggregates # return aggregate results
|
265
|
+
|
266
|
+
|
267
|
+
# Time-Series Aggregate
|
268
|
+
# Accepted intervals are: year, quarter, month, week, day, and hour
|
269
|
+
|
270
|
+
options = {
|
271
|
+
# get count of comments posted by day
|
272
|
+
aggregate: "value.posted:time_series:day"
|
273
|
+
}
|
274
|
+
|
275
|
+
query = "*"
|
276
|
+
|
277
|
+
response = client.search(:comments, query, options)
|
278
|
+
|
279
|
+
response.aggregates # return aggregate results
|
280
|
+
|
281
|
+
|
282
|
+
# Multiple Aggregate Functions
|
283
|
+
options = {
|
284
|
+
# multiple aggregate params are separated by commas
|
285
|
+
aggregate: "value.price:stats,value.num_sold:stats,value.num_sold:range:*~99:1~10:5~*"
|
286
|
+
}
|
287
|
+
|
288
|
+
query = "*"
|
289
|
+
|
290
|
+
response = client.search(:products, query, options)
|
291
|
+
|
292
|
+
response.aggregates # return aggregate results
|
293
|
+
```
|
294
|
+
|
176
295
|
### Examples and Documentation
|
177
296
|
|
178
297
|
There are more examples at [Orchestrate's API Documentation][apidoc] and documentation in the [rdoc][].
|
@@ -277,10 +396,19 @@ end
|
|
277
396
|
|
278
397
|
## Release Notes
|
279
398
|
|
399
|
+
### January 7, 2014: release 0.11.0
|
400
|
+
- **BACKWARDS-INCOMPATIBLE** `Orchestrate::Collection` searches require `#find` method at the end of the method call/chain. Example: `users.search('foo').find`.
|
401
|
+
- Implement `Orchestrate::Search` module, refactor functionality of prior `Orchestrate::Collection::SearchResults`.
|
402
|
+
- Implement results enumeration & request firing functionality in prior `Orchestrate::Collection::SearchResults` to `Orchestrate::Search::Results`
|
403
|
+
- Implement `Search::QueryBuilder` to construct `Collection` search queries.
|
404
|
+
- Implement `Search::AggregateBuilder` to construct aggregate params on `Collection` search queries.
|
405
|
+
- Implement `Search::StatsBuilder`, `Search::RangeBuilder`, `Search::DistanceBuilder`, & `Search::TimeSeriesBuilder` to construct aggregate function clauses for aggregate params.
|
406
|
+
- Implement `Search::AggregateResult` objects to repesent aggregate results returned from `Collection` search.
|
407
|
+
|
280
408
|
### December 11, 2014: release 0.10.0
|
281
409
|
- **BACKWARDS-INCOMPATIBLE** Prior `KeyValue#update` & `KeyValue#update!` renamed to `KeyValue#set` & `KeyValue#set!`. `KeyValue#update` now used after `PATCH` operations to fire the request.
|
282
410
|
- Implement `Collection#near` & `Collection#in`, allowing `Collection` to perform geo queries.
|
283
|
-
- Implement `Client#patch`, `Client#patch_merge`, allowing `Client` to perform
|
411
|
+
- Implement `Client#patch`, `Client#patch_merge`, allowing `Client` to perform partial updates through `PATCH` requests.
|
284
412
|
- Implement `KeyValue::OperationSet`, allowing a set of `PATCH` operations to be built by `KeyValue` through `KeyValue#add`, `KeyValue#remove`, `KeyValue#replace`, `KeyValue#move`, `KeyValue#copy`, `KeyValue#increment`, `KeyValue#decrement`, & `KeyValue#test`. The `KeyValue::OperationSet` is fired by ending the chain with `KeyValue#update`.
|
285
413
|
- Implement `KeyValue#merge`, allowing `KeyValue` to merge partial values into existing keys through `PATCH` requests.
|
286
414
|
|
@@ -346,4 +474,4 @@ end
|
|
346
474
|
### May 21, 2014: release 0.5.0
|
347
475
|
Initial Port from @jimcar
|
348
476
|
- Uses Faraday HTTP Library as backend, with examples of alternate adapters
|
349
|
-
- Cleanup client method signatures
|
477
|
+
- Cleanup client method signatures
|
@@ -109,6 +109,9 @@ module Orchestrate::API
|
|
109
109
|
# @return [Array] The items in the response.
|
110
110
|
attr_reader :results
|
111
111
|
|
112
|
+
# @return [Array] The aggregate items in the response.
|
113
|
+
attr_reader :aggregates
|
114
|
+
|
112
115
|
# @return [String] The location for the next page of results
|
113
116
|
attr_reader :next_link
|
114
117
|
|
@@ -122,6 +125,7 @@ module Orchestrate::API
|
|
122
125
|
@count = body['count']
|
123
126
|
@total_count = body['total_count']
|
124
127
|
@results = body['results']
|
128
|
+
@aggregates = body['aggregates']
|
125
129
|
@next_link = body['next']
|
126
130
|
@prev_link = body['prev']
|
127
131
|
end
|
@@ -345,17 +345,13 @@ module Orchestrate
|
|
345
345
|
end
|
346
346
|
end
|
347
347
|
|
348
|
-
# @!group Searching
|
349
|
-
# [Search the items in a collection](http://orchestrate.io/docs/api/#search) using a Lucene
|
350
|
-
# Query Syntax.
|
351
348
|
# @param query [#to_s] The [Lucene Query
|
352
349
|
# String](http://lucene.apache.org/core/4_3_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#Overview)
|
353
350
|
# to query the collection with.
|
354
|
-
# @return [
|
351
|
+
# @return [Orchestrate::Search::QueryBuilder] A builder object to construct the query.
|
355
352
|
def search(query)
|
356
|
-
|
353
|
+
Search::QueryBuilder.new(self, query)
|
357
354
|
end
|
358
|
-
# @!endgroup
|
359
355
|
|
360
356
|
# @!group Geo Queries
|
361
357
|
# Performs a search for items near a specified geographic point in a collection.
|
@@ -366,11 +362,11 @@ module Orchestrate
|
|
366
362
|
# @param distance [Integer] The number of distance units.
|
367
363
|
# @param units [#to_s] Unit of measurement for distance, default to kilometers (km),
|
368
364
|
# supported units: km, m, cm, mm, mi, yd, ft, in, nmi
|
369
|
-
# @return [
|
365
|
+
# @return [Orchestrate::Search::QueryBuilder] A builder object to construct the query.
|
370
366
|
def near(field, latitude, longitude, distance, units=nil)
|
371
|
-
|
372
|
-
|
373
|
-
|
367
|
+
units ||= 'km'
|
368
|
+
query = "#{field}:NEAR:{lat:#{latitude} lon:#{longitude} dist:#{distance}#{units}}"
|
369
|
+
Search::QueryBuilder.new(self, query)
|
374
370
|
end
|
375
371
|
|
376
372
|
# Performs a search for items within a particular area,
|
@@ -380,112 +376,14 @@ module Orchestrate
|
|
380
376
|
# @param box [#to_json] The values to create the bounding box,
|
381
377
|
# @example
|
382
378
|
# collection.in(:field, {north: 12.5, south: 15, east: 14, west: 3})
|
383
|
-
# @return [
|
379
|
+
# @return [Orchestrate::Search::QueryBuilder] A builder object to construct the query.
|
384
380
|
def in(field, box={})
|
385
381
|
box = box.flatten.each_slice(2).map {|dir, val| "#{dir}:#{val}" }.join(" ")
|
386
382
|
query = "#{field}:IN:{#{box}}"
|
387
|
-
|
383
|
+
Search::QueryBuilder.new(self, query)
|
388
384
|
end
|
389
385
|
# @!endgroup
|
390
386
|
|
391
|
-
# An enumerator with a query for searching an Orchestrate::Collection
|
392
|
-
class SearchResults
|
393
|
-
# @return [Collection] The collection this object will search.
|
394
|
-
attr_reader :collection
|
395
|
-
|
396
|
-
# @return [#to_s] The Lucene Query String given as the search query.
|
397
|
-
attr_reader :query
|
398
|
-
|
399
|
-
# @return [#to_s] The sorting parameters.
|
400
|
-
attr_reader :sort
|
401
|
-
|
402
|
-
# @return [Integer] The number of results to fetch per request.
|
403
|
-
attr_reader :limit
|
404
|
-
|
405
|
-
# Initialize a new SearchResults object
|
406
|
-
# @param collection [Orchestrate::Collection] The collection to search.
|
407
|
-
# @param query [#to_s] The Lucene Query to perform.
|
408
|
-
def initialize(collection, query, sort=nil)
|
409
|
-
@collection = collection
|
410
|
-
@query = query
|
411
|
-
@sort = sort
|
412
|
-
@limit = 100
|
413
|
-
@offset= nil
|
414
|
-
end
|
415
|
-
|
416
|
-
# Sets the sorting parameters for enumeration over the SearchResults items in the collection.
|
417
|
-
# #order takes multiple arguments, but each even numbered argument must be either :asc or :desc
|
418
|
-
# When given a single argument #order defaults to :asc
|
419
|
-
# @example
|
420
|
-
# @app[:items].search("location: Portland").order(:name, :asc, :rank, :desc, :created_at)
|
421
|
-
# the :created_at parameter will default to :asc
|
422
|
-
def order(*args)
|
423
|
-
sort = args.each_slice(2).map {|field, dir| dir ||= :asc; "#{field}:#{dir}" }.join(",")
|
424
|
-
self.class.new(collection, query, sort)
|
425
|
-
end
|
426
|
-
|
427
|
-
include Enumerable
|
428
|
-
|
429
|
-
# Iterates over each result from the Search. Used as the basis for Enumerable methods. Items are
|
430
|
-
# provided on the basis of score, with most relevant first.
|
431
|
-
# @overload each
|
432
|
-
# @return Enumerator
|
433
|
-
# @overload each(&block)
|
434
|
-
# @yieldparam [Array<(Float, Orchestrate::KeyValue)>] score,key_value The item's score and the item.
|
435
|
-
# @example
|
436
|
-
# collection.search("trendy").take(5).each do |score, item|
|
437
|
-
# puts "#{item.key} has a trend score of #{score}"
|
438
|
-
# end
|
439
|
-
def each
|
440
|
-
params = {limit:limit}
|
441
|
-
params[:offset] = offset if offset
|
442
|
-
params[:sort] = sort if sort
|
443
|
-
@response ||= collection.perform(:search, query, params)
|
444
|
-
return enum_for(:each) unless block_given?
|
445
|
-
raise ResultsNotReady.new if collection.app.inside_parallel?
|
446
|
-
loop do
|
447
|
-
@response.results.each do |listing|
|
448
|
-
yield [ listing['score'], KeyValue.from_listing(collection, listing, @response) ]
|
449
|
-
end
|
450
|
-
break unless @response.next_link
|
451
|
-
@response = @response.next_results
|
452
|
-
end
|
453
|
-
@response = nil
|
454
|
-
end
|
455
|
-
|
456
|
-
# Creates a Lazy Enumerator for the Search Results. If called inside its
|
457
|
-
# app's `in_parallel` block, will pre-fetch results.
|
458
|
-
def lazy
|
459
|
-
return each.lazy if collection.app.inside_parallel?
|
460
|
-
super
|
461
|
-
end
|
462
|
-
|
463
|
-
# Returns the first n items. Equivalent to Enumerable#take. Sets the
|
464
|
-
# `limit` parameter on the query to Orchestrate, so we don't ask for more than is needed.
|
465
|
-
# @param count [Integer] The number of items to limit to.
|
466
|
-
# @return [Array]
|
467
|
-
def take(count)
|
468
|
-
@limit = count > 100 ? 100 : count
|
469
|
-
super(count)
|
470
|
-
end
|
471
|
-
|
472
|
-
# Sets the offset for the query to Orchestrate, so you can skip items. Does not fire a request.
|
473
|
-
# Impelemented as separate method from drop, unlike #take, because take is a more common use case.
|
474
|
-
# @overload offset
|
475
|
-
# @return [Integer, nil] The number of items to skip. Nil is equivalent to zero.
|
476
|
-
# @overload offset(conunt)
|
477
|
-
# @param count [Integer] The number of items to skip.
|
478
|
-
# @return [SearchResults] self.
|
479
|
-
def offset(count=nil)
|
480
|
-
if count
|
481
|
-
@offset = count
|
482
|
-
self
|
483
|
-
else
|
484
|
-
@offset
|
485
|
-
end
|
486
|
-
end
|
487
|
-
end
|
488
|
-
|
489
387
|
# Tells the Applicaiton to perform a request on its client, automatically
|
490
388
|
# providing the collection name.
|
491
389
|
# @param api_method [Symbol] The method on the client to call.
|
@@ -0,0 +1,290 @@
|
|
1
|
+
module Orchestrate::Search
|
2
|
+
# Aggregate Builder object for constructing aggregate params included in a search
|
3
|
+
class AggregateBuilder
|
4
|
+
|
5
|
+
# @return [QueryBuilder]
|
6
|
+
attr_reader :builder
|
7
|
+
|
8
|
+
# @return [Array] Aggregate param arguments
|
9
|
+
attr_reader :aggregates
|
10
|
+
|
11
|
+
extend Forwardable
|
12
|
+
|
13
|
+
# Initialize a new AggregateBuilder object
|
14
|
+
# @param builder [Orchestrate::Search::SearchBuilder] The Search Builder object
|
15
|
+
def initialize(builder)
|
16
|
+
@builder = builder
|
17
|
+
@aggregates = []
|
18
|
+
end
|
19
|
+
|
20
|
+
def_delegator :@builder, :options
|
21
|
+
def_delegator :@builder, :order
|
22
|
+
def_delegator :@builder, :limit
|
23
|
+
def_delegator :@builder, :offset
|
24
|
+
def_delegator :@builder, :aggregate
|
25
|
+
def_delegator :@builder, :find
|
26
|
+
def_delegator :@builder, :collection
|
27
|
+
|
28
|
+
# @return Pretty-Printed string representation of the AggregateBuilder object
|
29
|
+
def to_s
|
30
|
+
"#<Orchestrate::Search::AggregateBuilder collection=#{collection.name} query=#{builder.query} aggregate=#{to_param}>"
|
31
|
+
end
|
32
|
+
alias :inspect :to_s
|
33
|
+
|
34
|
+
# @return constructed aggregate string parameter for search query
|
35
|
+
def to_param
|
36
|
+
aggregates.map {|agg| agg.to_param }.join(',')
|
37
|
+
end
|
38
|
+
|
39
|
+
# @!group Aggregate Functions
|
40
|
+
|
41
|
+
# @param field_name [#to_s]
|
42
|
+
# @return [AggregateBuilder]
|
43
|
+
def stats(field_name)
|
44
|
+
stat = StatsBuilder.new(self, "#{field_name}")
|
45
|
+
aggregates << stat
|
46
|
+
stat
|
47
|
+
end
|
48
|
+
|
49
|
+
# @param field_name [#to_s]
|
50
|
+
# @return [RangeBuilder]
|
51
|
+
def range(field_name)
|
52
|
+
rng = RangeBuilder.new(self, "#{field_name}")
|
53
|
+
aggregates << rng
|
54
|
+
rng
|
55
|
+
end
|
56
|
+
|
57
|
+
# @param field_name [#to_s]
|
58
|
+
# @return [DistanceBuilder]
|
59
|
+
def distance(field_name)
|
60
|
+
dist = DistanceBuilder.new(self, "#{field_name}")
|
61
|
+
aggregates << dist
|
62
|
+
dist
|
63
|
+
end
|
64
|
+
|
65
|
+
# @param field_name [#to_s]
|
66
|
+
# @return [TimeSeriesBuilder]
|
67
|
+
def time_series(field_name)
|
68
|
+
time = TimeSeriesBuilder.new(self, "#{field_name}")
|
69
|
+
aggregates << time
|
70
|
+
time
|
71
|
+
end
|
72
|
+
# @!endgroup
|
73
|
+
end
|
74
|
+
|
75
|
+
# Stats Builder object for constructing stats functions to be included in the aggregate param
|
76
|
+
class StatsBuilder
|
77
|
+
|
78
|
+
# @return [AggregateBuilder]
|
79
|
+
attr_reader :builder
|
80
|
+
|
81
|
+
# @return [#to_s] The field to operate over
|
82
|
+
attr_reader :field_name
|
83
|
+
|
84
|
+
extend Forwardable
|
85
|
+
|
86
|
+
# Initialize a new RangeBuilder object
|
87
|
+
# @param builder [AggregateBuilder] The Aggregate Builder object
|
88
|
+
# @param field_name [#to_s]
|
89
|
+
def initialize(builder, field_name)
|
90
|
+
@builder = builder
|
91
|
+
@field_name = field_name
|
92
|
+
end
|
93
|
+
|
94
|
+
def_delegator :@builder, :options
|
95
|
+
def_delegator :@builder, :order
|
96
|
+
def_delegator :@builder, :limit
|
97
|
+
def_delegator :@builder, :offset
|
98
|
+
def_delegator :@builder, :aggregate
|
99
|
+
def_delegator :@builder, :find
|
100
|
+
def_delegator :@builder, :stats
|
101
|
+
def_delegator :@builder, :range
|
102
|
+
def_delegator :@builder, :distance
|
103
|
+
def_delegator :@builder, :time_series
|
104
|
+
def_delegator :@builder, :collection
|
105
|
+
|
106
|
+
# @return Pretty-Printed string representation of the StatsBuilder object
|
107
|
+
def to_s
|
108
|
+
"#<Orchestrate::Search::StatsBuilder collection=#{collection.name} field_name=#{field_name}>"
|
109
|
+
end
|
110
|
+
alias :inspect :to_s
|
111
|
+
|
112
|
+
# @return [#to_s] constructed aggregate string clause
|
113
|
+
def to_param
|
114
|
+
"#{field_name}:stats"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Range Builder object for constructing range functions to be included in the aggregate param
|
119
|
+
class RangeBuilder
|
120
|
+
|
121
|
+
# @return [AggregateBuilder]
|
122
|
+
attr_reader :builder
|
123
|
+
|
124
|
+
# @return [#to_s] The field to operate over
|
125
|
+
attr_reader :field_name
|
126
|
+
|
127
|
+
# @return [#to_s] The range sets
|
128
|
+
attr_reader :ranges
|
129
|
+
|
130
|
+
extend Forwardable
|
131
|
+
|
132
|
+
# Initialize a new RangeBuilder object
|
133
|
+
# @param builder [AggregateBuilder] The Aggregate Builder object
|
134
|
+
# @param field_name [#to_s]
|
135
|
+
def initialize(builder, field_name)
|
136
|
+
@builder = builder
|
137
|
+
@field_name = field_name
|
138
|
+
@ranges = ''
|
139
|
+
end
|
140
|
+
|
141
|
+
def_delegator :@builder, :options
|
142
|
+
def_delegator :@builder, :order
|
143
|
+
def_delegator :@builder, :limit
|
144
|
+
def_delegator :@builder, :offset
|
145
|
+
def_delegator :@builder, :aggregate
|
146
|
+
def_delegator :@builder, :find
|
147
|
+
def_delegator :@builder, :stats
|
148
|
+
def_delegator :@builder, :range
|
149
|
+
def_delegator :@builder, :distance
|
150
|
+
def_delegator :@builder, :time_series
|
151
|
+
def_delegator :@builder, :collection
|
152
|
+
|
153
|
+
# @return Pretty-Printed string representation of the RangeBuilder object
|
154
|
+
def to_s
|
155
|
+
"#<Orchestrate::Search::RangeBuilder collection=#{collection.name} field_name=#{field_name} ranges=#{ranges}>"
|
156
|
+
end
|
157
|
+
alias :inspect :to_s
|
158
|
+
|
159
|
+
# @return [#to_s] constructed aggregate string clause
|
160
|
+
def to_param
|
161
|
+
"#{field_name}:range:#{ranges}"
|
162
|
+
end
|
163
|
+
|
164
|
+
# @param x [Integer]
|
165
|
+
# @return [RangeBuilder]
|
166
|
+
def below(x)
|
167
|
+
@ranges << "*~#{x}:"
|
168
|
+
self
|
169
|
+
end
|
170
|
+
|
171
|
+
# @param x [Integer]
|
172
|
+
# @return [RangeBuilder]
|
173
|
+
def above(x)
|
174
|
+
@ranges << "#{x}~*:"
|
175
|
+
self
|
176
|
+
end
|
177
|
+
|
178
|
+
# @param x [Integer]
|
179
|
+
# @param y [Integer]
|
180
|
+
# @return [RangeBuilder]
|
181
|
+
def between(x, y)
|
182
|
+
@ranges << "#{x}~#{y}:"
|
183
|
+
self
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
# Distance Builder object for constructing distance functions for the aggregate param
|
188
|
+
class DistanceBuilder < RangeBuilder
|
189
|
+
|
190
|
+
# @return Pretty-Printed string representation of the DistanceBuilder object
|
191
|
+
def to_s
|
192
|
+
"#<Orchestrate::Search::DistanceBuilder collection=#{collection.name} field_name=#{field_name} ranges=#{ranges}>"
|
193
|
+
end
|
194
|
+
alias :inspect :to_s
|
195
|
+
|
196
|
+
# @return [#to_s] constructed aggregate string clause
|
197
|
+
def to_param
|
198
|
+
"#{field_name}:distance:#{ranges}"
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
# Time Series Builder object for constructing time series functions for the aggregate param
|
203
|
+
class TimeSeriesBuilder
|
204
|
+
|
205
|
+
# @return [AggregateBuilder]
|
206
|
+
attr_reader :builder
|
207
|
+
|
208
|
+
# @return [#to_s] The field to operate over
|
209
|
+
attr_reader :field_name
|
210
|
+
|
211
|
+
# @return [#to_s] The interval of time for the TimeSeries function
|
212
|
+
attr_reader :interval
|
213
|
+
|
214
|
+
extend Forwardable
|
215
|
+
|
216
|
+
# Initialize a new TimeSeriesBuilder object
|
217
|
+
# @param builder [AggregateBuilder] The Aggregate Builder object
|
218
|
+
# @param field_name [#to_s] The field to operate over
|
219
|
+
def initialize(builder, field_name)
|
220
|
+
@builder = builder
|
221
|
+
@field_name = field_name
|
222
|
+
@interval = nil
|
223
|
+
end
|
224
|
+
|
225
|
+
def_delegator :@builder, :options
|
226
|
+
def_delegator :@builder, :order
|
227
|
+
def_delegator :@builder, :limit
|
228
|
+
def_delegator :@builder, :offset
|
229
|
+
def_delegator :@builder, :aggregate
|
230
|
+
def_delegator :@builder, :find
|
231
|
+
def_delegator :@builder, :stats
|
232
|
+
def_delegator :@builder, :range
|
233
|
+
def_delegator :@builder, :distance
|
234
|
+
def_delegator :@builder, :time_series
|
235
|
+
def_delegator :@builder, :collection
|
236
|
+
|
237
|
+
# @return Pretty-Printed string representation of the TimeSeriesBuilder object
|
238
|
+
def to_s
|
239
|
+
"#<Orchestrate::Search::TimeSeriesBuilder collection=#{collection.name} field_name=#{field_name} interval=#{interval}>"
|
240
|
+
end
|
241
|
+
alias :inspect :to_s
|
242
|
+
|
243
|
+
# @return [#to_s] constructed aggregate string clause
|
244
|
+
def to_param
|
245
|
+
"#{field_name}:time_series:#{interval}"
|
246
|
+
end
|
247
|
+
|
248
|
+
# Set time series interval to year
|
249
|
+
# @return [AggregateBuilder]
|
250
|
+
def year
|
251
|
+
@interval = 'year'
|
252
|
+
self
|
253
|
+
end
|
254
|
+
|
255
|
+
# Set time series interval to quarter
|
256
|
+
# @return [AggregateBuilder]
|
257
|
+
def quarter
|
258
|
+
@interval = 'quarter'
|
259
|
+
self
|
260
|
+
end
|
261
|
+
|
262
|
+
# Set time series interval to month
|
263
|
+
# @return [AggregateBuilder]
|
264
|
+
def month
|
265
|
+
@interval = 'month'
|
266
|
+
self
|
267
|
+
end
|
268
|
+
|
269
|
+
# Set time series interval to week
|
270
|
+
# @return [AggregateBuilder]
|
271
|
+
def week
|
272
|
+
@interval = 'week'
|
273
|
+
self
|
274
|
+
end
|
275
|
+
|
276
|
+
# Set time series interval to day
|
277
|
+
# @return [AggregateBuilder]
|
278
|
+
def day
|
279
|
+
@interval = 'day'
|
280
|
+
self
|
281
|
+
end
|
282
|
+
|
283
|
+
# Set time series interval to hour
|
284
|
+
# @return [AggregateBuilder]
|
285
|
+
def hour
|
286
|
+
@interval = 'hour'
|
287
|
+
self
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|