diff --git a/CHANGELOG b/CHANGELOG index fec4b82..fd0c925 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,8 @@ +* chain a separate search with "or_search" to find records matching either one + + search("foo").or_search(:conditions => { :priority => 3 }) + + *0.2.6* (July 6th, 2009) * search for field conditions in query string, only supported by ClassicQueryParser diff --git a/features/finding.feature b/features/finding.feature index f486aeb..752715f 100644 --- a/features/finding.feature +++ b/features/finding.feature @@ -119,7 +119,6 @@ Scenario: Query for separate OR conditions When I query "age" matching "17" or "name" matching "Jack" Then I should find records named "Jane, Jack" -@focus Scenario: Query for condition in keywords string Given the following indexed records | name | age | @@ -128,3 +127,12 @@ Scenario: Query for condition in keywords string | Jack | 17 | When I query for "age:17" Then I should find records named "Jane, Jack" + +Scenario: Query for separate OR conditions and keywords + Given the following indexed records + | name | age | + | John | 23 | + | Jane | 17 | + | Jack | 18 | + When I query for "John" or "age" matching "18" ordered by "name" + Then I should find records named "Jack, John" diff --git a/features/step_definitions/xapit_steps.rb b/features/step_definitions/xapit_steps.rb index 926811e..b727667 100644 --- a/features/step_definitions/xapit_steps.rb +++ b/features/step_definitions/xapit_steps.rb @@ -78,6 +78,10 @@ @records = XapitMember.search(:conditions => [{ field1.to_sym => value1 }, { field2.to_sym => value2 }]) end +When /^I query for "([^\"]*)" or "([^\"]*)" matching "([^\"]*)" ordered by "([^\"]*)"$/ do |keywords, field, value, order| + @records = XapitMember.search(keywords, :order => order).or_search(:conditions => { field.to_sym => value }) +end + When /^I query "([^\"]*)" between (\d+) and (\d+)$/ do |field, beginning, ending| @records = XapitMember.search(:conditions => { field.to_sym => beginning.to_i..ending.to_i }) end diff --git a/lib/xapit/collection.rb b/lib/xapit/collection.rb index b1c3cd4..2102cab 100644 --- a/lib/xapit/collection.rb +++ b/lib/xapit/collection.rb @@ -56,12 +56,32 @@ def last # Perform another search on this one, inheriting all options already passed. # See Xapit::Membership for search options. - def search(keywords, options = {}) - collection = Collection.new(@query_parser.member_class, keywords, options) + # + # Article.search("kite").search("sky") # only performs one query + # + def search(*args) + collection = Collection.new(@query_parser.member_class, *args) collection.base_query = @query_parser.query collection end + # Chain another search returning all records matched by either this search or the previous search + # Inherits all options passed in earlier search (such as :page and :order) + # See Xapit::Membership for search options. + # + # Article.search("kite").or_search(:conditions => { :priority => 1 }) + # + def or_search(*args) + collection = Collection.new(@query_parser.member_class, *args) + collection.base_query = @query_parser.base_query.dup # TODO duplication is necessary here because query is later modified, maybe I should make query immutable. + collection.extra_queries << @query_parser.query + collection + end + + def query + @query_parser.query + end + def base_query=(base_query) @query_parser.base_query = base_query end @@ -70,6 +90,14 @@ def base_query @query_parser.base_query end + def extra_queries=(extra_queries) + @query_parser.extra_queries = extra_queries + end + + def extra_queries + @query_parser.extra_queries + end + # The page number we are currently on. def current_page @query_parser.current_page diff --git a/lib/xapit/query_parsers/abstract_query_parser.rb b/lib/xapit/query_parsers/abstract_query_parser.rb index ee3ef62..c539880 100644 --- a/lib/xapit/query_parsers/abstract_query_parser.rb +++ b/lib/xapit/query_parsers/abstract_query_parser.rb @@ -2,14 +2,24 @@ module Xapit class AbstractQueryParser attr_reader :member_class attr_writer :base_query + attr_accessor :extra_queries def initialize(*args) @options = args.extract_options! @member_class = args[0] @search_text = args[1].to_s + @extra_queries = [] end def query + if @extra_queries.blank? + primary_query + else + primary_query.or_query(@extra_queries, :or) + end + end + + def primary_query if (@search_text.split + condition_terms + not_condition_terms + facet_terms).empty? base_query else