vendor/riddle/lib/riddle/client.rb in ultrasphinx-1.9 vs vendor/riddle/lib/riddle/client.rb in ultrasphinx-1.11

- old
+ new

@@ -24,19 +24,21 @@ # client.filters << Riddle::Client::Filter.new("birthday", # Time.at(1975, 1, 1).to_i..Time.at(1985, 1, 1).to_i, false) # class Client Commands = { - :search => 0, # SEARCHD_COMMAND_SEARCH - :excerpt => 1, # SEARCHD_COMMAND_EXCERPT - :update => 2 # SEARCHD_COMMAND_UPDATE + :search => 0, # SEARCHD_COMMAND_SEARCH + :excerpt => 1, # SEARCHD_COMMAND_EXCERPT + :update => 2, # SEARCHD_COMMAND_UPDATE + :keywords => 3 # SEARCHD_COMMAND_KEYWORDS } Versions = { - :search => 0x112, # VER_COMMAND_SEARCH - :excerpt => 0x100, # VER_COMMAND_EXCERPT - :update => 0x101 # VER_COMMAND_UPDATE + :search => 0x113, # VER_COMMAND_SEARCH + :excerpt => 0x100, # VER_COMMAND_EXCERPT + :update => 0x101, # VER_COMMAND_UPDATE + :keywords => 0x100 # VER_COMMAND_KEYWORDS } Statuses = { :ok => 0, # SEARCHD_OK :error => 1, # SEARCHD_ERROR @@ -48,11 +50,11 @@ :all => 0, # SPH_MATCH_ALL :any => 1, # SPH_MATCH_ANY :phrase => 2, # SPH_MATCH_PHRASE :boolean => 3, # SPH_MATCH_BOOLEAN :extended => 4, # SPH_MATCH_EXTENDED - :fullsacn => 5, # SPH_MATCH_FULLSCAN + :fullscan => 5, # SPH_MATCH_FULLSCAN :extended2 => 6 # SPH_MATCH_EXTENDED2 } RankModes = { :proximity_bm25 => 0, # SPH_RANK_PROXIMITY_BM25 @@ -156,12 +158,12 @@ } end # Append a query to the queue. This uses the same parameters as the query # method. - def append_query(search, index = '*') - @queue << query_message(search, index) + def append_query(search, index = '*', comments = '') + @queue << query_message(search, index, comments) end # Run all the queries currently in the queue. This will return an array of # results hashes. def run @@ -202,18 +204,13 @@ doc = is_64_bit > 0 ? response.next_64bit_int : response.next_int weight = response.next_int result[:matches] << {:doc => doc, :weight => weight, :index => i, :attributes => {}} result[:attribute_names].each do |attr| - case result[:attributes][attr] - when AttributeTypes[:float] - result[:matches].last[:attributes][attr] = response.next_float - when AttributeTypes[:multi] - result[:matches].last[:attributes][attr] = response.next_int_array - else - result[:matches].last[:attributes][attr] = response.next_int - end + result[:matches].last[:attributes][attr] = attribute_from_type( + result[:attributes][attr], response + ) end end result[:total] = response.next_int.to_i || 0 result[:total_found] = response.next_int.to_i || 0 @@ -273,12 +270,12 @@ # # <tt>:status</tt> is the error code for the query - and if there was a # related warning, it will be under the <tt>:warning</tt> key. Fatal errors # will be described under <tt>:error</tt>. # - def query(search, index = '*') - @queue << query_message(search, index) + def query(search, index = '*', comments = '') + @queue << query_message(search, index, comments) self.run.first end # Build excerpts from search terms (the +words+) and the text of documents. Excerpts are bodies of text that have the +words+ highlighted. # They may also be abbreviated to fit within a word limit. @@ -356,10 +353,34 @@ ) response.next_int end + # Generates a keyword list for a given query. Each keyword is represented + # by a hash, with keys :tokenised and :normalised. If return_hits is set to + # true it will also report on the number of hits and documents for each + # keyword (see :hits and :docs keys respectively). + def keywords(query, index, return_hits = false) + response = Response.new request( + :keywords, + keywords_message(query, index, return_hits) + ) + + (0...response.next_int).collect do + hash = {} + hash[:tokenised] = response.next + hash[:normalised] = response.next + + if return_hits + hash[:docs] = response.next_int + hash[:hits] = response.next_int + end + + hash + end + end + private # Connects to the Sphinx daemon, and yields a socket to use. The socket is # closed at the end of the block. def connect(&block) @@ -437,11 +458,11 @@ raise ResponseError, "Unknown searchd error (status: #{status})" end end # Generation of the message to send to Sphinx for a search. - def query_message(search, index) + def query_message(search, index, comments = '') message = Message.new # Mode, Limits, Sort Mode message.append_ints @offset, @limit, MatchModes[@match_mode], RankModes[@rank_mode], SortModes[@sort_mode] @@ -498,10 +519,12 @@ @field_weights.each do |key,val| message.append_string key message.append_int val end + message.append_string comments + message.to_s end # Generation of the message to send to Sphinx for an excerpts request. def excerpts_message(options) @@ -541,8 +564,30 @@ message.append_64bit_int key # document ID message.append_ints *values # array of new values (integers) end message.to_s + end + + # Generates the simple message to send to the daemon for a keywords request. + def keywords_message(query, index, return_hits) + message = Message.new + + message.append_string query + message.append_string index + message.append_int return_hits ? 1 : 0 + + message.to_s + end + + def attribute_from_type(type, response) + type -= AttributeTypes[:multi] if is_multi = type > AttributeTypes[:multi] + + case type + when AttributeTypes[:float] + is_multi ? response.next_float_array : response.next_float + else + is_multi ? response.next_int_array : response.next_int + end end end end