-
Notifications
You must be signed in to change notification settings - Fork 25
Expand file tree
/
Copy pathmulti_search.rb
More file actions
117 lines (106 loc) · 3.81 KB
/
multi_search.rb
File metadata and controls
117 lines (106 loc) · 3.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# frozen_string_literal: true
module ElastomerClient
class Client
# Execute an array of searches in bulk. Results are returned in an
# array in the order the queries were sent.
#
# The `multi_search` method can be used in two ways. Without a block
# the method will perform an API call, and it requires a bulk request
# body and optional request parameters.
#
# See https://www.elastic.co/guide/en/elasticsearch/reference/current/search-multi-search.html
#
# body - Request body as a String (required if a block is not given)
# params - Optional request parameters as a Hash
# block - Passed to a MultiSearch instance which assembles the searches
# into a single request.
#
# Examples
#
# # index and type in request body
# multi_search(request_body)
#
# # index in URI
# multi_search(request_body, index: 'default-index')
#
# # block form
# multi_search(index: 'default-index') do |m|
# m.search({query: {match_all: {}}, size: 0)
# m.search({query: {field: {"foo" => "bar"}}}, type: 'default-type')
# ...
# end
#
# Returns the response body as a Hash
def multi_search(body = nil, params = nil)
if block_given?
params, body = (body || {}), nil
yield msearch_obj = MultiSearch.new(self, params)
msearch_obj.call
else
raise "multi_search request body cannot be nil" if body.nil?
params ||= {}
response = self.post "{/index}{/type}/_msearch", params.merge(body:, action: "msearch", rest_api: "msearch")
response.body
end
end
alias_method :msearch, :multi_search
# The MultiSearch class is a helper for accumulating and submitting
# multi_search API requests. Instances of the MultiSearch class
# accumulate searches and then issue a single API request to
# Elasticsearch, which runs all accumulated searches in parallel
# and returns each result hash aggregated into an array of result
# hashes.
#
# Instead of instantiating this class directly, use
# the block form of Client#multi_search.
#
class MultiSearch
# Create a new MultiSearch instance for accumulating searches and
# submitting them all as a single request.
#
# client - ElastomerClient::Client used for HTTP requests to the server
# params - Parameters Hash to pass to the Client#multi_search method
def initialize(client, params = {})
@client = client
@params = params
@actions = []
end
attr_reader :client
# Add a search to the multi search request. This search will not
# be executed until the multi_search API call is made.
#
# query - The query body as a Hash
# params - Parameters Hash
#
# Returns this MultiSearch instance.
def search(query, params = {})
add_to_actions(params)
add_to_actions(query)
end
# Execute the multi_search call with the accumulated searches. If
# the accumulated actions list is empty then no action is taken.
#
# Returns the response body Hash.
def call
return if @actions.empty?
body = @actions.join("\n") + "\n"
client.multi_search(body, @params)
ensure
@actions.clear
end
# Internal: Add an action to the pending request. Actions can be
# either search params or query bodies. The first action must be
# a search params hash, followed by a query body, then alternating
# params and queries.
#
# action - the Hash (params or query) to add to the pending request
#
# Returns this MultiSearch instance.
def add_to_actions(action)
action = MultiJson.dump action
@actions << action
self
end
end
end
end