Commit 1569a146711cb6c5e98b20223fc23771823c1f83

Authored by Oskar Szrajer
1 parent 6a71a686

[#90] - include facets constrains on demand

.gitignore
... ... @@ -17,3 +17,4 @@ test/version_tmp
17 17 tmp
18 18 *.log
19 19 .DS_Store
  20 +.ruby-*
... ...
README.md
... ... @@ -416,6 +416,14 @@ price_ranges = [{to: 20}, {from: 20, to: 50}, {from: 50}]
416 416 Product.search "*", facets: {price: {ranges: price_ranges}}
417 417 ```
418 418  
  419 +With basic constrains
  420 +
  421 +* `include_constraints` - if set to true will use constrains from basic query inside facets
  422 +
  423 +```ruby
  424 +Product.search('*', where: { color: 'red' }, facets: {store_id: {where: {in_stock: false}}}, include_constraints: true)
  425 +```
  426 +
419 427 ### Highlight
420 428  
421 429 Highlight the search query in the results.
... ...
lib/searchkick/query.rb
... ... @@ -239,6 +239,7 @@ module Searchkick
239 239 # offset is not possible
240 240 # http://elasticsearch-users.115913.n3.nabble.com/Is-pagination-possible-in-termsStatsFacet-td3422943.html
241 241  
  242 + facet_options.deep_merge!(where: options[:where].reject{|k| k == field}) if options[:include_constraints] == true
242 243 facet_filters = where_filters(facet_options[:where])
243 244 if facet_filters.any?
244 245 payload[:facets][field][:facet_filter] = {
... ... @@ -428,4 +429,4 @@ module Searchkick
428 429 end
429 430  
430 431 end
431   -end
432 432 \ No newline at end of file
  433 +end
... ...
test/facets_test.rb
... ... @@ -5,9 +5,10 @@ class TestFacets < Minitest::Unit::TestCase
5 5 def setup
6 6 super
7 7 store [
8   - {name: "Product Show", store_id: 1, in_stock: true, color: "blue", price: 21},
9   - {name: "Product Hide", store_id: 2, in_stock: false, color: "green", price: 25},
10   - {name: "Product B", store_id: 2, in_stock: false, color: "red", price: 5}
  8 + {name: "Product Show", latitude: 37.7833, longitude: 12.4167, store_id: 1, in_stock: true, color: "blue", price: 21},
  9 + {name: "Product Hide", latitude: 29.4167, longitude: -98.5000, store_id: 2, in_stock: false, color: "green", price: 25},
  10 + {name: "Product B", latitude: 43.9333, longitude: -122.4667, store_id: 2, in_stock: false, color: "red", price: 5},
  11 + {name: "Foo", latitude: 43.9333, longitude: 12.4667, store_id: 3, in_stock: false, color: "yellow", price: 15}
11 12 ]
12 13 end
13 14  
... ... @@ -37,4 +38,73 @@ class TestFacets < Minitest::Unit::TestCase
37 38 assert_equal 0, facet["ranges"][1]["count"]
38 39 assert_equal 2, facet["ranges"][2]["count"]
39 40 end
  41 + def test_constraints
  42 + facets = Product.search("Product", where: { in_stock: true },
  43 + facets: [:store_id], include_constraints: true).facets
  44 +
  45 + assert_equal 1, facets['store_id']['terms'].size
  46 + assert_equal [1], facets['store_id']['terms'].map{|f| f['term']}
  47 + end
  48 +
  49 + def test_constraints_with_location
  50 + facets = Product.search("Product", where: {location: {near: [37, -122], within: "2000mi"}},
  51 + facets: [:store_id], include_constraints: true).facets
  52 +
  53 + assert_equal 1, facets['store_id']['terms'].size
  54 + assert_equal 2, facets['store_id']['terms'][0]['term']
  55 + end
  56 +
  57 + def test_constraints_with_location_and_or_statement
  58 + facets = Product.search("Product", where: {or: [[
  59 + { location: {near: [37, -122], within: "2000mi"}}, {color: 'blue'}
  60 + ]]}, facets: [:store_id], include_constraints: true).facets
  61 +
  62 + assert_equal 2, facets['store_id']['terms'].size
  63 + assert_equal [1, 2], facets['store_id']['terms'].map{|f| f['term']}.sort
  64 + end
  65 +
  66 + def test_facets_and_basic_constrains_together
  67 + facets = Product.search("Product", where: { color: 'red' },
  68 + facets: {store_id: {where: {in_stock: false}}}, include_constraints: true).facets
  69 +
  70 + assert_equal 1, facets['store_id']['terms'].size
  71 + assert_equal 2, facets['store_id']['terms'][0]['term']
  72 + assert_equal 1, facets['store_id']['terms'][0]['count']
  73 + end
  74 +
  75 + def test_facets_without_basic_constrains
  76 + facets = Product.search("Product", where: { color: 'red' },
  77 + facets: {store_id: {where: {in_stock: false}}}, include_constraints: false).facets
  78 +
  79 + assert_equal 1, facets['store_id']['terms'].size
  80 + assert_equal 2, facets['store_id']['terms'][0]['term']
  81 + assert_equal 2, facets['store_id']['terms'][0]['count']
  82 + end
  83 +
  84 + def test_do_not_include_current_facets_filter
  85 + facets = Product.search("Product", where: { store_id: 2 },
  86 + facets: [:store_id], include_constraints: true).facets
  87 +
  88 + assert_equal 2, facets['store_id']['terms'].size
  89 + assert_equal [1, 2], facets['store_id']['terms'].map{|f| f['term']}.sort
  90 + end
  91 +
  92 + def test_do_not_include_current_facets_filter_with_complex_call
  93 + facets = Product.search("Product", where: { store_id: 2, price: {gte: 4 }},
  94 + facets: [:store_id], include_constraints: true).facets
  95 +
  96 + assert_equal 2, facets['store_id']['terms'].size
  97 + assert_equal [1, 2], facets['store_id']['terms'].map{|f| f['term']}.sort
  98 + end
  99 +
  100 + def test_should_still_limit_results
  101 + results = Product.search("*", where: { store_id: 2, price: {gte: 4 }},
  102 + facets: [:in_stock, :store_id, :color], include_constraints: false)
  103 +
  104 + facets = results.facets
  105 + assert_equal 2, results.size
  106 + assert_equal ["Product B", "Product Hide"], results.map(&:name).sort
  107 + assert_equal 3, facets['store_id']['terms'].size
  108 + assert_equal [1, 2, 3], facets['store_id']['terms'].map{|f| f['term']}.sort
  109 + end
40 110 end
... ...