-
Notifications
You must be signed in to change notification settings - Fork 25
/
multi_percolate.rb
129 lines (117 loc) · 4.49 KB
/
multi_percolate.rb
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
118
119
120
121
122
123
124
125
126
127
128
129
# frozen_string_literal: true
module ElastomerClient
class Client
# Execute an array of percolate actions in bulk. Results are returned in an
# array in the order the actions were sent.
#
# The `multi_percolate` 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-percolate.html#_multi_percolate_api
#
# body - Request body as a String (required if a block is not given)
# params - Optional request parameters as a Hash
# block - Passed to a MultiPercolate instance which assembles the
# percolate actions into a single request.
#
# Examples
#
# # index and type in request body
# multi_percolate(request_body)
#
# # index in URI
# multi_percolate(request_body, index: 'default-index')
#
# # block form
# multi_percolate(index: 'default-index') do |m|
# m.percolate({ author: "pea53" }, { type: 'default-type' })
# m.count({ author: "pea53" }, { type: 'type2' })
# ...
# end
#
# Returns the response body as a Hash
def multi_percolate(body = nil, params = nil)
if block_given?
params, body = (body || {}), nil
yield mpercolate_obj = MultiPercolate.new(self, params)
mpercolate_obj.call
else
raise "multi_percolate request body cannot be nil" if body.nil?
params ||= {}
response = self.post "{/index}{/type}/_mpercolate", params.merge(body:, action: "mpercolate", rest_api: "mpercolate")
response.body
end
end
alias_method :mpercolate, :multi_percolate
# The MultiPercolate class is a helper for accumulating and submitting
# multi_percolate API requests. Instances of the MultiPercolate class
# accumulate percolate actions and then issue a single API request to
# Elasticsearch, which runs all accumulated percolate actions 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_percolate.
#
class MultiPercolate
# Create a new MultiPercolate instance for accumulating percolate actions
# 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_percolate method
def initialize(client, params = {})
@client = client
@params = params
@actions = []
end
attr_reader :client
# Add a percolate action to the multi percolate request. This percolate
# action will not be executed until the multi_percolate API call is made.
#
# header - A Hash of the index and type, if not provided in the params
# doc - A Hash of the document
#
# Returns this MultiPercolate instance.
def percolate(doc, header = {})
add_to_actions(percolate: @params.merge(header))
add_to_actions(doc:)
end
# Add a percolate acount action to the multi percolate request. This
# percolate count action will not be executed until the multi_percolate
# API call is made.
#
# header - A Hash of the index and type, if not provided in the params
# doc - A Hash of the document
#
# Returns this MultiPercolate instance.
def count(doc, header = {})
add_to_actions(count: @params.merge(header))
add_to_actions(doc:)
end
# Execute the multi_percolate call with the accumulated percolate actions.
# 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_percolate(body, @params)
ensure
@actions.clear
end
# Internal: Add an action to the pending request. Actions can be
# either headers or bodies. The first action must be a percolate header,
# followed by a body, then alternating headers and bodies.
#
# action - the Hash (header or body) to add to the pending request
#
# Returns this MultiPercolate instance.
def add_to_actions(action)
action = MultiJson.dump action
@actions << action
self
end
end
end
end