lib/picky/search.rb in picky-3.0.0.pre1 vs lib/picky/search.rb in picky-3.0.0.pre2
- old
+ new
@@ -1,146 +1,99 @@
+# encoding: utf-8
+#
module Picky
- # = Picky Queries
+ # = Picky Searches
#
# A Picky Search is an object which:
- # * holds one or more indexes
- # * offers an interface to query these indexes.
+ # * holds one or more indexes
+ # * offers an interface to query these indexes.
#
# You connect URL paths to indexes via a Query.
#
- # We recommend not to use this directly, but connect it to an URL and query through one of these
+ # We recommend to not use this directly, but connect it to an URL and query through one of these
# (Protip: Use "curl 'localhost:8080/query/path?query=exampletext')" in a Terminal.
#
class Search
include Helpers::Measuring
attr_reader :indexes
- attr_writer :tokenizer
- attr_accessor :weights
+ attr_accessor :tokenizer, :weights
# Takes:
# * A number of indexes
- # * Options hash (optional) with:
- # * tokenizer: Tokenizers::Query.default by default.
- # * weights: A hash of weights, or a Query::Weights object.
#
# TODO Add identifiers_to_remove (rename) and reduce_allocations_to_amount (rename).
# TODO categories_to_remove ?
#
# It is also possible to define the tokenizer and weights like so.
# Example:
- # Search.new(index1, index2, index3) do
+ # search = Search.new(index1, index2, index3) do
# searching removes_characters: /[^a-z]/, etc.
# weights [:author, :title] => +3, [:title, :isbn] => +1
# end
#
def initialize *index_definitions
- options = Hash === index_definitions.last ? index_definitions.pop : {}
-
@indexes = Query::Indexes.new *index_definitions, combinations_type_for(index_definitions)
- searching options[:tokenizer]
- boost options[:weights]
instance_eval(&Proc.new) if block_given?
+
+ @tokenizer ||= Tokenizers::Query.default
+ @weights ||= Query::Weights.new
+
+ self
end
- # Example:
- # Search.new(index1, index2, index3) do
- # searching removes_characters: /[^a-z]/, etc.
- # weights [:author, :title] => +3, [:title, :isbn] => +1
+ # Examples:
+ # search = Search.new(index1, index2, index3) do
+ # searching removes_characters: /[^a-z]/,
+ # # etc.
# end
#
+ # search = Search.new(index1, index2, index3) do
+ # searching MyTokenizerThatRespondsToTheMethodTokenize.new
+ # end
+ #
def searching options
@tokenizer = if options.respond_to?(:tokenize)
options
else
options && Tokenizers::Query.new(options)
end
end
- # Returns the tokenizer if set or if not, the query tokenizer.
- #
- def tokenizer
- @tokenizer || Tokenizers::Query.default
- end
-
# Example:
- # Search.new(index1, index2, index3) do
- # searching removes_characters: /[^a-z]/, etc.
- # boost [:author, :title] => +3, [:title, :isbn] => +1
+ # search = Search.new(books_index, dvd_index, mp3_index) do
+ # boost [:author, :title] => +3,
+ # [:title, :isbn] => +1
# end
#
- def boost options
- weights = options || Query::Weights.new
+ def boost weights
+ weights ||= Query::Weights.new
@weights = Hash === weights ? Query::Weights.new(weights) : weights
end
- # Returns the right combinations strategy for
- # a number of query indexes.
- #
- # Currently it isn't possible using Memory and Redis etc.
- # indexes in the same query index group.
- #
- # Picky will raise a Query::Indexes::DifferentTypesError.
- #
- @@mapping = {
- Indexes::Memory => Query::Combinations::Memory,
- Indexes::Redis => Query::Combinations::Redis
- }
- def combinations_type_for index_definitions_ary
- index_types = extract_index_types index_definitions_ary
- !index_types.empty? && @@mapping[*index_types] || Query::Combinations::Memory
- end
- def extract_index_types index_definitions_ary
- index_types = index_definitions_ary.map(&:class)
- index_types.uniq!
- check_index_types index_types
- index_types
- end
- def check_index_types index_types
- raise_different index_types if index_types.size > 1
- end
- # Currently it isn't possible using Memory and Redis etc.
- # indexes in the same query index group.
- #
- class DifferentTypesError < StandardError
- def initialize types
- @types = types
- end
- def to_s
- "Currently it isn't possible to mix #{@types.join(" and ")} Indexes in the same Search instance."
- end
- end
- def raise_different index_types
- raise DifferentTypesError.new(index_types)
- end
-
# This is the main entry point for a query.
# Use this in specs and also for running queries.
#
# Parameters:
# * text: The search text.
# * ids = 20: _optional_ The amount of ids to calculate (with offset).
# * offset = 0: _optional_ The offset from which position to return the ids. Useful for pagination.
#
# Note: The Rack adapter calls this method after unravelling the HTTP request.
#
- # TODO Rename to search.
- #
- def search_with_text text, ids = 20, offset = 0
- search tokenized(text), ids.to_i, offset.to_i
+ def search text, ids = 20, offset = 0
+ search_with tokenized(text), ids.to_i, offset.to_i
end
# Runs the actual search using Query::Tokens.
#
- # Note: Internal method, use #search_with_text.
+ # Note: Internal method, use #search
#
- # TODO Rename to search_with.
- #
- def search tokens, ids = 20, offset = 0
+ def search_with tokens, ids = 20, offset = 0
results = nil
duration = timed do
results = execute tokens, ids, offset
end
@@ -149,11 +102,11 @@
results
end
# Execute a search using Query::Tokens.
#
- # Note: Internal method, use #search_with_text.
+ # Note: Internal method, use #search.
#
def execute tokens, ids, offset
Results.from ids, offset, sorted_allocations(tokens)
end
@@ -168,9 +121,49 @@
# Gets sorted allocations for the tokens.
#
def sorted_allocations tokens # :nodoc:
indexes.prepared_allocations_for tokens, weights
+ end
+
+ # Returns the right combinations strategy for
+ # a number of query indexes.
+ #
+ # Currently it isn't possible using Memory and Redis etc.
+ # indexes in the same query index group.
+ #
+ # Picky will raise a Query::Indexes::DifferentTypesError.
+ #
+ @@mapping = {
+ Indexes::Memory => Query::Combinations::Memory,
+ Indexes::Redis => Query::Combinations::Redis
+ }
+ def combinations_type_for index_definitions_ary
+ index_types = extract_index_types index_definitions_ary
+ !index_types.empty? && @@mapping[*index_types] || Query::Combinations::Memory
+ end
+ def extract_index_types index_definitions_ary
+ index_types = index_definitions_ary.map(&:class)
+ index_types.uniq!
+ check_index_types index_types
+ index_types
+ end
+ def check_index_types index_types
+ raise_different index_types if index_types.size > 1
+ end
+ # Currently it isn't possible using Memory and Redis etc.
+ # indexes in the same query index group.
+ #
+ class DifferentTypesError < StandardError
+ def initialize types
+ @types = types
+ end
+ def to_s
+ "Currently it isn't possible to mix #{@types.join(" and ")} Indexes in the same Search instance."
+ end
+ end
+ def raise_different index_types
+ raise DifferentTypesError.new(index_types)
end
# Display some nice information for the user.
#
def to_s
\ No newline at end of file