Commit a43437726e4b22e541e93498c0e3473663d4644c
1 parent
0c5c0dd1
Exists in
master
and in
21 other branches
Added advanced facet options
Showing
3 changed files
with
77 additions
and
40 deletions
Show diff stats
README.md
lib/searchkick/search.rb
... | ... | @@ -54,54 +54,82 @@ module Searchkick |
54 | 54 | |
55 | 55 | # where |
56 | 56 | # TODO expand or |
57 | - (options[:where] || {}).each do |field, value| | |
58 | - if field == :or | |
59 | - value.each do |or_clause| | |
60 | - filter :or, or_clause.map{|or_statement| {term: or_statement} } | |
61 | - end | |
62 | - else | |
63 | - # expand ranges | |
64 | - if value.is_a?(Range) | |
65 | - value = {gte: value.first, (value.exclude_end? ? :lt : :lte) => value.last} | |
66 | - end | |
67 | 57 | |
68 | - if value.is_a?(Array) # in query | |
69 | - filter :terms, {field => value} | |
70 | - elsif value.is_a?(Hash) | |
71 | - value.each do |op, op_value| | |
72 | - if op == :not | |
73 | - if op_value.is_a?(Array) | |
74 | - filter :not, {terms: {field => op_value}} | |
75 | - else | |
76 | - filter :not, {term: {field => op_value}} | |
77 | - end | |
78 | - else | |
79 | - range_query = | |
80 | - case op | |
81 | - when :gt | |
82 | - {from: op_value, include_lower: false} | |
83 | - when :gte | |
84 | - {from: op_value, include_lower: true} | |
85 | - when :lt | |
86 | - {to: op_value, include_upper: false} | |
87 | - when :lte | |
88 | - {to: op_value, include_upper: true} | |
58 | + where_filters = | |
59 | + proc do |where| | |
60 | + filters = [] | |
61 | + (where || {}).each do |field, value| | |
62 | + if field == :or | |
63 | + value.each do |or_clause| | |
64 | + filters << {or: or_clause.map{|or_statement| {term: or_statement} }} | |
65 | + end | |
66 | + else | |
67 | + # expand ranges | |
68 | + if value.is_a?(Range) | |
69 | + value = {gte: value.first, (value.exclude_end? ? :lt : :lte) => value.last} | |
70 | + end | |
71 | + | |
72 | + if value.is_a?(Array) # in query | |
73 | + filters << {terms: {field => value}} | |
74 | + elsif value.is_a?(Hash) | |
75 | + value.each do |op, op_value| | |
76 | + if op == :not # not equal | |
77 | + if op_value.is_a?(Array) | |
78 | + filters << {not: {terms: {field => op_value}}} | |
79 | + else | |
80 | + filters << {not: {term: {field => op_value}}} | |
81 | + end | |
89 | 82 | else |
90 | - raise "Unknown where operator" | |
83 | + range_query = | |
84 | + case op | |
85 | + when :gt | |
86 | + {from: op_value, include_lower: false} | |
87 | + when :gte | |
88 | + {from: op_value, include_lower: true} | |
89 | + when :lt | |
90 | + {to: op_value, include_upper: false} | |
91 | + when :lte | |
92 | + {to: op_value, include_upper: true} | |
93 | + else | |
94 | + raise "Unknown where operator" | |
95 | + end | |
96 | + filters << {range: {field => range_query}} | |
91 | 97 | end |
92 | - filter :range, field => range_query | |
98 | + end | |
99 | + else | |
100 | + filters << {term: {field => value}} | |
93 | 101 | end |
94 | 102 | end |
95 | - else | |
96 | - filter :term, {field => value} | |
97 | 103 | end |
104 | + filters | |
98 | 105 | end |
106 | + | |
107 | + where_filters.call(options[:where]).each do |f| | |
108 | + type, value = f.first | |
109 | + filter type, value | |
99 | 110 | end |
100 | - (options[:facets] || []).each do |field| | |
101 | - facet field do | |
102 | - terms field | |
111 | + | |
112 | + # facets | |
113 | + if options[:facets] | |
114 | + facets = options[:facets] || {} | |
115 | + if facets.is_a?(Array) # convert to more advanced syntax | |
116 | + facets = Hash[ facets.map{|f| [f, {}] } ] | |
117 | + end | |
118 | + | |
119 | + facets.each do |field, facet_options| | |
120 | + facet_filters = where_filters.call(facet_options[:where]) | |
121 | + facet field do | |
122 | + terms field | |
123 | + if facet_filters.size == 1 | |
124 | + type, value = facet_filters.first.first | |
125 | + facet_filter type, value | |
126 | + elsif facet_filters.size > 1 | |
127 | + facet_filter :and, *facet_filters | |
128 | + end | |
129 | + end | |
103 | 130 | end |
104 | 131 | end |
132 | + | |
105 | 133 | end |
106 | 134 | end |
107 | 135 | end | ... | ... |
test/searchkick_test.rb
... | ... | @@ -248,10 +248,13 @@ class TestSearchkick < Minitest::Unit::TestCase |
248 | 248 | |
249 | 249 | def test_facets |
250 | 250 | store [ |
251 | - {name: "Product Show", store_id: 1}, | |
252 | - {name: "Product Hide", store_id: 2} | |
251 | + {name: "Product Show", store_id: 1, in_stock: true, color: "blue"}, | |
252 | + {name: "Product Hide", store_id: 2, in_stock: false, color: "green"}, | |
253 | + {name: "Product B", store_id: 2, in_stock: false, color: "red"} | |
253 | 254 | ] |
254 | 255 | assert_equal 2, Product.search("Product", facets: [:store_id]).facets["store_id"]["terms"].size |
256 | + assert_equal 1, Product.search("Product", facets: {store_id: {where: {in_stock: true}}}).facets["store_id"]["terms"].size | |
257 | + assert_equal 1, Product.search("Product", facets: {store_id: {where: {in_stock: true, color: "blue"}}}).facets["store_id"]["terms"].size | |
255 | 258 | end |
256 | 259 | |
257 | 260 | protected | ... | ... |