diff --git a/README.md b/README.md index 9467daf..0f0678d 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,12 @@ explain: true Product.search "2% Milk", facets: [:store_id, :aisle_id] ``` +Advanced + +```ruby +Product.search "2% Milk", facets: {store_id: {where: {in_stock: true}}} +``` + ### Synonyms ```ruby diff --git a/lib/searchkick/search.rb b/lib/searchkick/search.rb index 0f58ae3..d59d43a 100644 --- a/lib/searchkick/search.rb +++ b/lib/searchkick/search.rb @@ -54,54 +54,82 @@ module Searchkick # where # TODO expand or - (options[:where] || {}).each do |field, value| - if field == :or - value.each do |or_clause| - filter :or, or_clause.map{|or_statement| {term: or_statement} } - end - else - # expand ranges - if value.is_a?(Range) - value = {gte: value.first, (value.exclude_end? ? :lt : :lte) => value.last} - end - if value.is_a?(Array) # in query - filter :terms, {field => value} - elsif value.is_a?(Hash) - value.each do |op, op_value| - if op == :not - if op_value.is_a?(Array) - filter :not, {terms: {field => op_value}} - else - filter :not, {term: {field => op_value}} - end - else - range_query = - case op - when :gt - {from: op_value, include_lower: false} - when :gte - {from: op_value, include_lower: true} - when :lt - {to: op_value, include_upper: false} - when :lte - {to: op_value, include_upper: true} + where_filters = + proc do |where| + filters = [] + (where || {}).each do |field, value| + if field == :or + value.each do |or_clause| + filters << {or: or_clause.map{|or_statement| {term: or_statement} }} + end + else + # expand ranges + if value.is_a?(Range) + value = {gte: value.first, (value.exclude_end? ? :lt : :lte) => value.last} + end + + if value.is_a?(Array) # in query + filters << {terms: {field => value}} + elsif value.is_a?(Hash) + value.each do |op, op_value| + if op == :not # not equal + if op_value.is_a?(Array) + filters << {not: {terms: {field => op_value}}} + else + filters << {not: {term: {field => op_value}}} + end else - raise "Unknown where operator" + range_query = + case op + when :gt + {from: op_value, include_lower: false} + when :gte + {from: op_value, include_lower: true} + when :lt + {to: op_value, include_upper: false} + when :lte + {to: op_value, include_upper: true} + else + raise "Unknown where operator" + end + filters << {range: {field => range_query}} end - filter :range, field => range_query + end + else + filters << {term: {field => value}} end end - else - filter :term, {field => value} end + filters end + + where_filters.call(options[:where]).each do |f| + type, value = f.first + filter type, value end - (options[:facets] || []).each do |field| - facet field do - terms field + + # facets + if options[:facets] + facets = options[:facets] || {} + if facets.is_a?(Array) # convert to more advanced syntax + facets = Hash[ facets.map{|f| [f, {}] } ] + end + + facets.each do |field, facet_options| + facet_filters = where_filters.call(facet_options[:where]) + facet field do + terms field + if facet_filters.size == 1 + type, value = facet_filters.first.first + facet_filter type, value + elsif facet_filters.size > 1 + facet_filter :and, *facet_filters + end + end end end + end end end diff --git a/test/searchkick_test.rb b/test/searchkick_test.rb index 54a10f2..dc26b4b 100644 --- a/test/searchkick_test.rb +++ b/test/searchkick_test.rb @@ -248,10 +248,13 @@ class TestSearchkick < Minitest::Unit::TestCase def test_facets store [ - {name: "Product Show", store_id: 1}, - {name: "Product Hide", store_id: 2} + {name: "Product Show", store_id: 1, in_stock: true, color: "blue"}, + {name: "Product Hide", store_id: 2, in_stock: false, color: "green"}, + {name: "Product B", store_id: 2, in_stock: false, color: "red"} ] assert_equal 2, Product.search("Product", facets: [:store_id]).facets["store_id"]["terms"].size + assert_equal 1, Product.search("Product", facets: {store_id: {where: {in_stock: true}}}).facets["store_id"]["terms"].size + assert_equal 1, Product.search("Product", facets: {store_id: {where: {in_stock: true, color: "blue"}}}).facets["store_id"]["terms"].size end protected -- libgit2 0.21.0