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