Permalink
Browse files

Add support for :exclude param to query facet

  • Loading branch information...
1 parent a253bed commit cc68aa8dd9279de7b89dd526fee98f6d130a60ed Cuong Hoang committed with brutuscat Oct 11, 2011
@@ -249,15 +249,9 @@ def facet(*field_names, &block)
"wrong number of arguments (#{field_names.length} for 1)"
)
end
- if options.has_key?(:exclude)
- raise(
- ArgumentError,
- "can't use :exclude with query facets"
- )
- end
search_facet = @search.add_query_facet(field_names.first, options)
Sunspot::Util.instance_eval_or_call(
- QueryFacet.new(@query, @setup, search_facet),
+ QueryFacet.new(@query, @setup, search_facet, options),
&block
)
elsif options[:only]
@@ -5,8 +5,8 @@ module DSL
# method.
#
class QueryFacet
- def initialize(query, setup, facet) #:nodoc:
- @query, @setup, @facet = query, setup, facet
+ def initialize(query, setup, facet, options) #:nodoc:
+ @query, @setup, @facet, @options = query, setup, facet, options
end
#
@@ -24,7 +24,7 @@ def initialize(query, setup, facet) #:nodoc:
# An object used to identify this facet row in the results.
#
def row(label, &block)
- query_facet = Sunspot::Query::QueryFacet.new
+ query_facet = Sunspot::Query::QueryFacet.new(@options)
Sunspot::Util.instance_eval_or_call(
Scope.new(@query.add_query_facet(query_facet), @setup),
&block
@@ -1,6 +1,17 @@
module Sunspot
module Query
class QueryFacet < Connective::Conjunction
+
+ def initialize(options = {}, negated = false)
+ if exclude_filters = options[:exclude]
+ @exclude_tag = Util.Array(exclude_filters).map do |filter|
+ filter.tag
+ end.join(',')
+ end
+ super(negated)
+ end
+
+
def to_params
if @components.empty?
{}
@@ -11,6 +22,32 @@ def to_params
}
end
end
+
+ def to_boolean_phrase
+ "#{to_local_params}#{super}"
+ end
+
+ private
+
+ def local_params
+ @local_params ||=
+ begin
+ local_params = {}
+ local_params[:ex] = @exclude_tag if @exclude_tag
+ local_params
+ end
+ end
+
+ def to_local_params
+ if local_params.empty?
+ ''
+ else
+ pairs = local_params.map do |key, value|
+ "#{key}=#{value}"
+ end
+ "{!#{pairs.join(' ')}}"
+ end
+ end
end
end
end
@@ -179,16 +179,6 @@
connection.should have_last_search_with(:"f.blog.facet.sort" => 'true')
end
- it 'raises an ArgumentError if exclusion attempted on a query facet' do
- lambda do
- search do
- blog_filter = with(:blog_id, 1)
- facet(:bad, :exclude => blog_filter) do
- row(:bogus) { with(:blog_id, 1) }
- end
- end
- end.should raise_error(ArgumentError)
- end
it 'raises an ArgumentError if exclusion attempted on a restricted field facet' do
lambda do
@@ -426,6 +416,58 @@
connection.searches.last[:"facet.query"].should be_a(String)
end
+ it 'tags and excludes a scope filter in a query facet' do
+ search do
+ blog_filter = with(:blog_id, 1)
+ facet:foo, :exclude => blog_filter do
+ row(:bar) do
+ with(:category_ids, 1)
+ end
+ end
+ end
+ filter_tag = get_filter_tag('blog_id_i:1')
+ connection.should have_last_search_with(
+ :"facet.query" => "{!ex=#{filter_tag}}category_ids_im:1"
+ )
+ end
+
+ it 'tags and excludes a disjunction filter in a query facet' do
+ search do
+ blog_filter = any_of do
+ with(:blog_id, 1)
+ with(:blog_id, 2)
+ end
+ facet:foo, :exclude => blog_filter do
+ row(:bar) do
+ with(:category_ids, 1)
+ end
+ end
+ end
+ filter_tag = get_filter_tag('(blog_id_i:1 OR blog_id_i:2)')
+ connection.should have_last_search_with(
+ :"facet.query" => "{!ex=#{filter_tag}}category_ids_im:1"
+ )
+ end
+
+ it 'tags and excludes multiple filters in a query facet' do
+ search do
+ blog_filter = with(:blog_id, 1)
+ category_filter = with(:category_ids, 2)
+ facet:foo, :exclude => [blog_filter, category_filter] do
+ row(:bar) do
+ with(:category_ids, 1)
+ end
+ end
+ end
+ filter_tags = %w(blog_id_i:1 category_ids_im:2).map do |phrase|
+ get_filter_tag(phrase)
+ end.join(',')
+ connection.should have_last_search_with(
+ :"facet.query" => "{!ex=#{filter_tags}}category_ids_im:1"
+ )
+ end
+
+
it 'ignores facet query with only empty rows' do
search do
facet :foo do
@@ -166,24 +166,70 @@ def self.test_field_type(name, attribute, field, *args)
)
end
- it 'should exclude filter from faceting' do
- search = Sunspot.search(Post) do
- with(:blog_id, 1)
- category_filter = with(:category_ids, 1)
- facet(:category_ids, :exclude => category_filter)
+ context 'field faceting' do
+ it 'should exclude filter from faceting' do
+ search = Sunspot.search(Post) do
+ with(:blog_id, 1)
+ category_filter = with(:category_ids, 1)
+ facet(:category_ids, :exclude => category_filter)
+ end
+ search.facet(:category_ids).rows.map { |row| row.value }.to_set.should == Set[1, 2]
+ end
+
+ it 'should use facet keys to facet more than once with different exclusions' do
+ search = Sunspot.search(Post) do
+ with(:blog_id, 1)
+ category_filter = with(:category_ids, 1)
+ facet(:category_ids)
+ facet(:category_ids, :exclude => category_filter, :name => :all_category_ids)
+ end
+ search.facet(:category_ids).rows.map { |row| row.value }.should == [1]
+ search.facet(:all_category_ids).rows.map { |row| row.value }.to_set.should == Set[1, 2]
end
- search.facet(:category_ids).rows.map { |row| row.value }.to_set.should == Set[1, 2]
end
- it 'should use facet keys to facet more than once with different exclusions' do
- search = Sunspot.search(Post) do
- with(:blog_id, 1)
- category_filter = with(:category_ids, 1)
- facet(:category_ids)
- facet(:category_ids, :exclude => category_filter, :name => :all_category_ids)
+ context 'query faceting' do
+ it 'should exclude filter from faceting' do
+ search = Sunspot.search(Post) do
+ with(:blog_id, 1)
+ category_filter = with(:category_ids, 1)
+ facet :category_ids, :exclude => category_filter do
+ row(:category_1) do
+ with(:category_ids, 1)
+ end
+ row(:category_2) do
+ with(:category_ids, 2)
+ end
+ end
+ end
+ search.facet(:category_ids).rows.map { |row| [row.value, row.count] }.to_set.should == Set[[:category_1, 1], [:category_2, 1]]
+ end
+
+ it 'should use facet keys to facet more than once with different exclusions' do
+ search = Sunspot.search(Post) do
+ with(:blog_id, 1)
+ category_filter = with(:category_ids, 1)
+ facet :category_ids do
+ row(:category_1) do
+ with(:category_ids, 1)
+ end
+ row(:category_2) do
+ with(:category_ids, 2)
+ end
+ end
+
+ facet :all_category_ids, :exclude => category_filter do
+ row(:category_1) do
+ with(:category_ids, 1)
+ end
+ row(:category_2) do
+ with(:category_ids, 2)
+ end
+ end
+ end
+ search.facet(:category_ids).rows.map { |row| [row.value, row.count] }.to_set.should == Set[[:category_1, 1]]
+ search.facet(:all_category_ids).rows.map { |row| [row.value, row.count] }.to_set.should == Set[[:category_1, 1], [:category_2, 1]]
end
- search.facet(:category_ids).rows.map { |row| row.value }.should == [1]
- search.facet(:all_category_ids).rows.map { |row| row.value }.to_set.should == Set[1, 2]
end
end

0 comments on commit cc68aa8

Please sign in to comment.