Commit 7f66ff26ee60316ba01209948d8806662d7be498

Authored by Andrew Kane
1 parent 7f8b301c

Added range and date_range aggregations

README.md
... ... @@ -578,9 +578,16 @@ Limit
578 578 Product.search "apples", aggs: {store_id: {limit: 10}}
579 579 ```
580 580  
  581 +Ranges
  582 +
  583 +```ruby
  584 +price_ranges = [{to: 20}, {from: 20, to: 50}, {from: 50}]
  585 +Product.search "*", aggs: {price: {ranges: price_ranges}}
  586 +```
  587 +
581 588 #### Moving From Facets
582 589  
583   -1. Replace `facets` with `aggs` in searches. **Note:** Range and stats facets are not supported at this time.
  590 +1. Replace `facets` with `aggs` in searches. **Note:** Stats facets are not supported at this time.
584 591  
585 592 ```ruby
586 593 products = Product.search "chuck taylor", facets: [:brand]
... ... @@ -627,6 +634,14 @@ Product.search "apples", aggs: {store_id: {limit: 10}}
627 634  
628 635 3. By default, `where` conditions apply to aggregations. This is equivalent to `smart_facets: true`. If you have `smart_facets: true`, you can remove it. If this is not desired, set `smart_aggs: false`.
629 636  
  637 +4. If you have any range facets with dates, change the key from `ranges` to `date_ranges`.
  638 +
  639 + ```ruby
  640 + facets: {date_field: {ranges: date_ranges}}
  641 + # to
  642 + aggs: {date_field: {date_ranges: date_ranges}}
  643 + ```
  644 +
630 645 ### Facets [deprecated]
631 646  
632 647 Facets have been deprecated in favor of aggregations as of Searchkick 0.9.2. See [how to upgrade](#moving-from-facets).
... ...
lib/searchkick/query.rb
... ... @@ -344,12 +344,28 @@ module Searchkick
344 344 aggs.each do |field, agg_options|
345 345 size = agg_options[:limit] ? agg_options[:limit] : 100_000
346 346  
347   - payload[:aggs][field] = {
348   - terms: {
349   - field: agg_options[:field] || field,
350   - size: size
  347 + if agg_options[:ranges]
  348 + payload[:aggs][field] = {
  349 + range: {
  350 + field: agg_options[:field] || field,
  351 + ranges: agg_options[:ranges]
  352 + }
351 353 }
352   - }
  354 + elsif agg_options[:date_ranges]
  355 + payload[:aggs][field] = {
  356 + date_range: {
  357 + field: agg_options[:field] || field,
  358 + ranges: agg_options[:date_ranges]
  359 + }
  360 + }
  361 + else
  362 + payload[:aggs][field] = {
  363 + terms: {
  364 + field: agg_options[:field] || field,
  365 + size: size
  366 + }
  367 + }
  368 + end
353 369  
354 370 where = {}
355 371 where = (options[:where] || {}).reject { |k| k == field } unless options[:smart_aggs] == false
... ...
test/aggs_test.rb
... ... @@ -32,6 +32,27 @@ class AggsTest < Minitest::Test
32 32 assert_equal(1, agg["sum_other_doc_count"]) if Gem::Version.new(Searchkick.server_version) >= Gem::Version.new("1.4.0")
33 33 end
34 34  
  35 + def test_ranges
  36 + price_ranges = [{to: 10}, {from: 10, to: 20}, {from: 20}]
  37 + agg = Product.search("Product", aggs: {price: {ranges: price_ranges}}).aggs["price"]
  38 +
  39 + assert_equal 3, agg["buckets"].size
  40 + assert_equal 10.0, agg["buckets"][0]["to"]
  41 + assert_equal 20.0, agg["buckets"][2]["from"]
  42 + assert_equal 1, agg["buckets"][0]["doc_count"]
  43 + assert_equal 0, agg["buckets"][1]["doc_count"]
  44 + assert_equal 2, agg["buckets"][2]["doc_count"]
  45 + end
  46 +
  47 + def test_date_ranges
  48 + ranges = [{to: 1.day.ago}, {from: 1.day.ago, to: 1.day.from_now}, {from: 1.day.from_now}]
  49 + agg = Product.search("Product", aggs: {created_at: {date_ranges: ranges}}).aggs["created_at"]
  50 +
  51 + assert_equal 1, agg["buckets"][0]["doc_count"]
  52 + assert_equal 1, agg["buckets"][1]["doc_count"]
  53 + assert_equal 1, agg["buckets"][2]["doc_count"]
  54 + end
  55 +
35 56 def test_query_where
36 57 assert_equal ({1 => 1}), store_agg(where: {in_stock: true}, aggs: [:store_id])
37 58 end
... ...