110 lines
3.5 KiB
Ruby
110 lines
3.5 KiB
Ruby
|
module Elasticsearch
|
||
|
module Model
|
||
|
|
||
|
# Contains functionality related to searching.
|
||
|
#
|
||
|
module Searching
|
||
|
|
||
|
# Wraps a search request definition
|
||
|
#
|
||
|
class SearchRequest
|
||
|
attr_reader :klass, :definition, :options
|
||
|
|
||
|
# @param klass [Class] The class of the model
|
||
|
# @param query_or_payload [String,Hash,Object] The search request definition
|
||
|
# (string, JSON, Hash, or object responding to `to_hash`)
|
||
|
# @param options [Hash] Optional parameters to be passed to the Elasticsearch client
|
||
|
#
|
||
|
def initialize(klass, query_or_payload, options={})
|
||
|
@klass = klass
|
||
|
@options = options
|
||
|
|
||
|
__index_name = options[:index] || klass.index_name
|
||
|
__document_type = options[:type] || klass.document_type
|
||
|
|
||
|
case
|
||
|
# search query: ...
|
||
|
when query_or_payload.respond_to?(:to_hash)
|
||
|
body = query_or_payload.to_hash
|
||
|
|
||
|
# search '{ "query" : ... }'
|
||
|
when query_or_payload.is_a?(String) && query_or_payload =~ /^\s*{/
|
||
|
body = query_or_payload
|
||
|
|
||
|
# search '...'
|
||
|
else
|
||
|
q = query_or_payload
|
||
|
end
|
||
|
|
||
|
if body
|
||
|
@definition = { index: __index_name, type: __document_type, body: body }.update options
|
||
|
else
|
||
|
@definition = { index: __index_name, type: __document_type, q: q }.update options
|
||
|
end
|
||
|
end
|
||
|
|
||
|
# Performs the request and returns the response from client
|
||
|
#
|
||
|
# @return [Hash] The response from Elasticsearch
|
||
|
#
|
||
|
def execute!
|
||
|
klass.client.search(@definition)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
module ClassMethods
|
||
|
|
||
|
# Provides a `search` method for the model to easily search within an index/type
|
||
|
# corresponding to the model settings.
|
||
|
#
|
||
|
# @param query_or_payload [String,Hash,Object] The search request definition
|
||
|
# (string, JSON, Hash, or object responding to `to_hash`)
|
||
|
# @param options [Hash] Optional parameters to be passed to the Elasticsearch client
|
||
|
#
|
||
|
# @return [Elasticsearch::Model::Response::Response]
|
||
|
#
|
||
|
# @example Simple search in `Article`
|
||
|
#
|
||
|
# Article.search 'foo'
|
||
|
#
|
||
|
# @example Search using a search definition as a Hash
|
||
|
#
|
||
|
# response = Article.search \
|
||
|
# query: {
|
||
|
# match: {
|
||
|
# title: 'foo'
|
||
|
# }
|
||
|
# },
|
||
|
# highlight: {
|
||
|
# fields: {
|
||
|
# title: {}
|
||
|
# }
|
||
|
# },
|
||
|
# size: 50
|
||
|
#
|
||
|
# response.results.first.title
|
||
|
# # => "Foo"
|
||
|
#
|
||
|
# response.results.first.highlight.title
|
||
|
# # => ["<em>Foo</em>"]
|
||
|
#
|
||
|
# response.records.first.title
|
||
|
# # Article Load (0.2ms) SELECT "articles".* FROM "articles" WHERE "articles"."id" IN (1, 3)
|
||
|
# # => "Foo"
|
||
|
#
|
||
|
# @example Search using a search definition as a JSON string
|
||
|
#
|
||
|
# Article.search '{"query" : { "match_all" : {} }}'
|
||
|
#
|
||
|
def search(query_or_payload, options={})
|
||
|
search = SearchRequest.new(self, query_or_payload, options)
|
||
|
|
||
|
Response::Response.new(self, search)
|
||
|
end
|
||
|
|
||
|
end
|
||
|
|
||
|
end
|
||
|
end
|
||
|
end
|