Commit b5763d73da146a2e492986eeb1c71103805e627b
1 parent
64301b0e
Exists in
master
and in
21 other branches
Added aggregates
Showing
3 changed files
with
109 additions
and
23 deletions
Show diff stats
README.md
... | ... | @@ -45,7 +45,7 @@ Add this line to your application’s Gemfile: |
45 | 45 | gem 'searchkick' |
46 | 46 | ``` |
47 | 47 | |
48 | -For Elasticsearch 0.90, use version `0.6.3` and [this readme](https://github.com/ankane/searchkick/blob/v0.6.3/README.md). | |
48 | +For Elasticsearch 2.0, use version `0.9.2` or above. For Elasticsearch 0.90, use version `0.6.3` and [this readme](https://github.com/ankane/searchkick/blob/v0.6.3/README.md). | |
49 | 49 | |
50 | 50 | Add searchkick to models you want to search. |
51 | 51 | |
... | ... | @@ -547,11 +547,95 @@ products = Product.search "peantu butta", suggest: true |
547 | 547 | products.suggestions # ["peanut butter"] |
548 | 548 | ``` |
549 | 549 | |
550 | -### Facets | |
550 | +### Aggregations | |
551 | 551 | |
552 | -[Facets](http://www.elasticsearch.org/guide/reference/api/search/facets/) provide aggregated search data. | |
552 | +[Aggregations](http://www.elasticsearch.org/guide/reference/api/search/facets/) provide aggregated search data. | |
553 | 553 | |
554 | - | |
554 | + | |
555 | + | |
556 | +```ruby | |
557 | +products = Product.search "chuck taylor", aggs: [:product_type, :gender, :brand] | |
558 | +products.aggs | |
559 | +``` | |
560 | + | |
561 | +By default, `where` conditions apply to aggregations. | |
562 | + | |
563 | +```ruby | |
564 | +Product.search "wingtips", where: {color: "brandy"}, aggs: [:size] | |
565 | +# aggregations for brandy wingtips are returned | |
566 | +``` | |
567 | + | |
568 | +Change this with: | |
569 | + | |
570 | +```ruby | |
571 | +Product.search "wingtips", where: {color: "brandy"}, aggs: [:size], smart_aggs: false | |
572 | +# aggregations for all wingtips are returned | |
573 | +``` | |
574 | + | |
575 | +Set `where` conditions for each aggregation separately with: | |
576 | + | |
577 | +```ruby | |
578 | +Product.search "wingtips", aggs: {size: {where: {color: "brandy"}}} | |
579 | +``` | |
580 | + | |
581 | +Limit | |
582 | + | |
583 | +```ruby | |
584 | +Product.search "apples", aggs: {store_id: {limit: 10}} | |
585 | +``` | |
586 | + | |
587 | +#### Moving From Facets | |
588 | + | |
589 | +1. Replace `facets` with `aggs` in searches. **Note:** Range and stats facets are not supported at this time. | |
590 | + | |
591 | + ```ruby | |
592 | + products = Product.search "chuck taylor", facets: [:brand] | |
593 | + # to | |
594 | + products = Product.search "chuck taylor", aggs: [:brand] | |
595 | + ``` | |
596 | + | |
597 | +2. Replace the `facets` method with `aggs` for results. | |
598 | + | |
599 | + ```ruby | |
600 | + products.facets | |
601 | + # to | |
602 | + products.aggs | |
603 | + ``` | |
604 | + | |
605 | + The keys in results differ slightly. Instead of: | |
606 | + | |
607 | + ```json | |
608 | + { | |
609 | + "_type":"terms", | |
610 | + "missing":0, | |
611 | + "total":45, | |
612 | + "other":34, | |
613 | + "terms":[ | |
614 | + {"term":14.0,"count":11} | |
615 | + ] | |
616 | + } | |
617 | + ``` | |
618 | + | |
619 | + You get: | |
620 | + | |
621 | + ```json | |
622 | + { | |
623 | + "doc_count":45, | |
624 | + "doc_count_error_upper_bound":0, | |
625 | + "sum_other_doc_count":34, | |
626 | + "buckets":[ | |
627 | + {"key":14.0,"doc_count":11} | |
628 | + ] | |
629 | + } | |
630 | + ``` | |
631 | + | |
632 | + Update your application to handle this. | |
633 | + | |
634 | +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`. | |
635 | + | |
636 | +### Facets [deprecated] | |
637 | + | |
638 | +Facets have been deprecated in favor of aggregations as of Searchkick 0.9.2. See [how to upgrade](#moving-from-facets). | |
555 | 639 | |
556 | 640 | ```ruby |
557 | 641 | products = Product.search "chuck taylor", facets: [:product_type, :gender, :brand] |
... | ... | @@ -693,6 +777,8 @@ City.search "san", boost_by_distance: {field: :location, origin: [37, -122], fun |
693 | 777 | |
694 | 778 | Searchkick supports [Elasticsearch’s routing feature](https://www.elastic.co/blog/customizing-your-document-routing). |
695 | 779 | |
780 | +**Note:** Routing is not yet supported for Elasticsearch 2.0. | |
781 | + | |
696 | 782 | ```ruby |
697 | 783 | class Contact < ActiveRecord::Base |
698 | 784 | searchkick routing: :user_id | ... | ... |
lib/searchkick/query.rb
... | ... | @@ -354,9 +354,9 @@ module Searchkick |
354 | 354 | } |
355 | 355 | } |
356 | 356 | |
357 | - agg_options.deep_merge!(where: options.fetch(:where, {}).reject { |k| k == field }) if options[:smart_aggs] == true | |
358 | - agg_filters = where_filters(agg_options[:where]) | |
359 | - | |
357 | + where = {} | |
358 | + where = (options[:where] || {}).reject { |k| k == field } unless options[:smart_aggs] == false | |
359 | + agg_filters = where_filters(where.merge(agg_options[:where] || {})) | |
360 | 360 | if agg_filters.any? |
361 | 361 | payload[:aggs][field] = { |
362 | 362 | filter: { | ... | ... |
test/aggs_test.rb
... | ... | @@ -32,34 +32,34 @@ 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_where_no_smart_aggs | |
36 | - assert_equal ({2 => 2}), store_agg(where: {color: "red"}, aggs: {store_id: {where: {in_stock: false}}}) | |
37 | - assert_equal ({2 => 2}), store_agg(where: {color: "blue"}, aggs: {store_id: {where: {in_stock: false}}}) | |
35 | + def test_query_where | |
36 | + assert_equal ({1 => 1}), store_agg(where: {in_stock: true}, aggs: [:store_id]) | |
38 | 37 | end |
39 | 38 | |
40 | - def test_smart_aggs | |
41 | - assert_equal ({1 => 1}), store_agg(where: {in_stock: true}, aggs: [:store_id], smart_aggs: true) | |
39 | + def test_two_wheres | |
40 | + assert_equal ({2 => 1}), store_agg(where: {color: "red"}, aggs: {store_id: {where: {in_stock: false}}}) | |
42 | 41 | end |
43 | 42 | |
44 | - def test_smart_aggs_where | |
45 | - assert_equal ({2 => 1}), store_agg(where: {color: "red"}, aggs: {store_id: {where: {in_stock: false}}}, smart_aggs: true) | |
43 | + def test_where_override | |
44 | + assert_equal ({}), store_agg(where: {color: "red"}, aggs: {store_id: {where: {in_stock: false, color: "blue"}}}) | |
45 | + assert_equal ({2 => 1}), store_agg(where: {color: "blue"}, aggs: {store_id: {where: {in_stock: false, color: "red"}}}) | |
46 | 46 | end |
47 | 47 | |
48 | - def test_smart_aggs_where_override | |
49 | - assert_equal ({2 => 1}), store_agg(where: {color: "red"}, aggs: {store_id: {where: {in_stock: false, color: "blue"}}}, smart_aggs: true) | |
50 | - assert_equal ({}), store_agg(where: {color: "blue"}, aggs: {store_id: {where: {in_stock: false, color: "red"}}}, smart_aggs: true) | |
48 | + def test_skip | |
49 | + assert_equal ({1 => 1, 2 => 2}), store_agg(where: {store_id: 2}, aggs: [:store_id]) | |
51 | 50 | end |
52 | 51 | |
53 | - def test_smart_aggs_skip_agg | |
54 | - assert_equal ({1 => 1, 2 => 2}), store_agg(where: {store_id: 2}, aggs: [:store_id], smart_aggs: true) | |
52 | + def test_skip_complex | |
53 | + assert_equal ({1 => 1, 2 => 1}), store_agg(where: {store_id: 2, price: {gt: 5}}, aggs: [:store_id]) | |
55 | 54 | end |
56 | 55 | |
57 | - def test_smart_aggs_skip_agg_complex | |
58 | - assert_equal ({1 => 1, 2 => 1}), store_agg(where: {store_id: 2, price: {gt: 5}}, aggs: [:store_id], smart_aggs: true) | |
56 | + def test_multiple | |
57 | + assert_equal ({"store_id" => {1 => 1, 2 => 2}, "color" => {"blue" => 1, "green" => 1, "red" => 1}}), store_multiple_aggs(aggs: [:store_id, :color]) | |
59 | 58 | end |
60 | 59 | |
61 | - def test_multiple_aggs | |
62 | - assert_equal ({"store_id" => {1 => 1, 2 => 2}, "color" => {"blue" => 1, "green" => 1, "red" => 1}}), store_multiple_aggs(aggs: [:store_id, :color]) | |
60 | + def test_smart_aggs_false | |
61 | + assert_equal ({2 => 2}), store_agg(where: {color: "red"}, aggs: {store_id: {where: {in_stock: false}}}, smart_aggs: false) | |
62 | + assert_equal ({2 => 2}), store_agg(where: {color: "blue"}, aggs: {store_id: {where: {in_stock: false}}}, smart_aggs: false) | |
63 | 63 | end |
64 | 64 | |
65 | 65 | protected | ... | ... |