es-elasticity 0.4.5 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/elasticity/multi_search.rb +8 -5
- data/lib/elasticity/search.rb +64 -42
- data/lib/elasticity/version.rb +1 -1
- data/spec/functional/persistence_spec.rb +1 -0
- data/spec/units/multi_search_spec.rb +7 -4
- data/spec/units/search_spec.rb +2 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 964aa0b0955363219b5b3258cfcf7341c9eccae7
|
4
|
+
data.tar.gz: e6379e81e8abba1a895a02e9d915f440e627f47f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ec06b056b633344895a0d045df11f365854e398bc7f10c109c4c2cfe827ee16a17ca73a41570faf116ea0d4dbd55274522a76ec94c88cf95a261f61edf56535a
|
7
|
+
data.tar.gz: 221d4232fbc52a63fd16bc309c4474295817ecb9133b21b742004e16a6ee4200f966290d8ad5e338bfb5d2abb9f808d40a4902bc727231366d645c2895ef011f
|
@@ -1,5 +1,6 @@
|
|
1
1
|
module Elasticity
|
2
2
|
class MultiSearch
|
3
|
+
|
3
4
|
def initialize
|
4
5
|
@searches = {}
|
5
6
|
@mappers = {}
|
@@ -23,12 +24,15 @@ module Elasticity
|
|
23
24
|
end
|
24
25
|
|
25
26
|
def [](name)
|
26
|
-
|
27
|
-
@results[name]
|
27
|
+
results_collection[name]
|
28
28
|
end
|
29
29
|
|
30
30
|
private
|
31
31
|
|
32
|
+
def results_collection
|
33
|
+
@results_collection ||= fetch
|
34
|
+
end
|
35
|
+
|
32
36
|
def fetch
|
33
37
|
bodies = @searches.values.map do |hsh|
|
34
38
|
hsh[:search_definition].to_msearch_args
|
@@ -37,7 +41,6 @@ module Elasticity
|
|
37
41
|
response = ActiveSupport::Notifications.instrument("multi_search.elasticity", args: { body: bodies }) do
|
38
42
|
Elasticity.config.client.msearch(body: bodies.map(&:dup))
|
39
43
|
end
|
40
|
-
|
41
44
|
results = {}
|
42
45
|
|
43
46
|
@searches.keys.each_with_index do |name, idx|
|
@@ -46,9 +49,9 @@ module Elasticity
|
|
46
49
|
|
47
50
|
results[name] = case
|
48
51
|
when search[:documents]
|
49
|
-
resp[
|
52
|
+
Search::Results.new(resp, search[:search_definition].body, search[:documents].method(:map_hit))
|
50
53
|
when search[:active_records]
|
51
|
-
Search::ActiveRecordProxy.
|
54
|
+
Search::ActiveRecordProxy.map_response(search[:active_records], search[:search_definition].body, resp)
|
52
55
|
end
|
53
56
|
end
|
54
57
|
|
data/lib/elasticity/search.rb
CHANGED
@@ -84,12 +84,11 @@ module Elasticity
|
|
84
84
|
class LazySearch
|
85
85
|
include Enumerable
|
86
86
|
|
87
|
-
delegate :each, :size, :length, :[], :+, :-, :&, :|,
|
87
|
+
delegate :each, :size, :length, :[], :+, :-, :&, :|, :total, :per_page,
|
88
|
+
:total_pages, :current_page, to: :search_results
|
88
89
|
|
89
90
|
attr_accessor :search_definition
|
90
91
|
|
91
|
-
DEFAULT_SIZE = 10
|
92
|
-
|
93
92
|
def initialize(client, search_definition, &mapper)
|
94
93
|
@client = client
|
95
94
|
@search_definition = search_definition
|
@@ -104,10 +103,6 @@ module Elasticity
|
|
104
103
|
empty?
|
105
104
|
end
|
106
105
|
|
107
|
-
def total
|
108
|
-
response["hits"]["total"]
|
109
|
-
end
|
110
|
-
|
111
106
|
def aggregations
|
112
107
|
response["aggregations"] ||= {}
|
113
108
|
end
|
@@ -121,31 +116,7 @@ module Elasticity
|
|
121
116
|
end
|
122
117
|
|
123
118
|
def search_results
|
124
|
-
|
125
|
-
|
126
|
-
hits = response["hits"]["hits"]
|
127
|
-
|
128
|
-
@search_results = if @mapper.nil?
|
129
|
-
hits
|
130
|
-
else
|
131
|
-
hits.map { |hit| @mapper.(hit) }
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
# for pagination
|
136
|
-
def per_page
|
137
|
-
@search_definition.body[:size] || DEFAULT_SIZE
|
138
|
-
end
|
139
|
-
|
140
|
-
# for pagination
|
141
|
-
def total_pages
|
142
|
-
(total.to_f / per_page.to_f).ceil
|
143
|
-
end
|
144
|
-
|
145
|
-
# for pagination
|
146
|
-
def current_page
|
147
|
-
return 1 if @search_definition.body[:from].nil?
|
148
|
-
@search_definition.body[:from] / per_page + 1
|
119
|
+
@search_results ||= Search::Results.new(response, @search_definition.body, @mapper)
|
149
120
|
end
|
150
121
|
|
151
122
|
private
|
@@ -199,10 +170,9 @@ module Elasticity
|
|
199
170
|
|
200
171
|
loop do
|
201
172
|
response = @client.scroll(scroll_id: response["_scroll_id"], scroll: @scroll)
|
202
|
-
|
203
|
-
break if hits.empty?
|
173
|
+
break if response["hits"]["hits"].empty?
|
204
174
|
|
205
|
-
y <<
|
175
|
+
y << Search::Results.new(response, @search_definition.body, @mapper)
|
206
176
|
end
|
207
177
|
end
|
208
178
|
end
|
@@ -216,21 +186,27 @@ module Elasticity
|
|
216
186
|
end
|
217
187
|
|
218
188
|
class ActiveRecordProxy
|
219
|
-
def self.
|
220
|
-
ids = hits.map { |hit| hit["_id"] }
|
189
|
+
def self.map_response(relation, body, response)
|
190
|
+
ids = response["hits"]["hits"].map { |hit| hit["_id"] }
|
221
191
|
|
222
192
|
if ids.any?
|
223
193
|
id_col = "#{relation.connection.quote_column_name(relation.table_name)}.#{relation.connection.quote_column_name(relation.klass.primary_key)}"
|
224
194
|
id_vals = ids.map { |id| relation.connection.quote(id) }
|
225
|
-
relation.where("#{id_col} IN (?)", ids).order("FIELD(#{id_col}, #{id_vals.join(',')})")
|
195
|
+
Relation.new(relation.where("#{id_col} IN (?)", ids).order("FIELD(#{id_col}, #{id_vals.join(',')})"), body, response)
|
226
196
|
else
|
227
|
-
relation.none
|
197
|
+
Relation.new(relation.none, body, response)
|
228
198
|
end
|
229
199
|
end
|
230
200
|
|
231
201
|
class Relation < ActiveSupport::ProxyObject
|
232
|
-
|
202
|
+
|
203
|
+
delegate :total, :per_page, :total_pages, :current_page, to: :@results
|
204
|
+
|
205
|
+
def initialize(relation, search_definition, response)
|
233
206
|
@relation = relation
|
207
|
+
@search_definition = search_definition
|
208
|
+
@response = response
|
209
|
+
@results = Results.new(response, search_definition)
|
234
210
|
end
|
235
211
|
|
236
212
|
def method_missing(name, *args, &block)
|
@@ -251,7 +227,7 @@ module Elasticity
|
|
251
227
|
def initialize(client, search_definition, relation)
|
252
228
|
@client = client
|
253
229
|
@search_definition = search_definition.update(_source: false)
|
254
|
-
@relation =
|
230
|
+
@relation = relation
|
255
231
|
end
|
256
232
|
|
257
233
|
def metadata
|
@@ -278,7 +254,7 @@ module Elasticity
|
|
278
254
|
|
279
255
|
def filtered_relation
|
280
256
|
return @filtered_relation if defined?(@filtered_relation)
|
281
|
-
@filtered_relation = ActiveRecordProxy.
|
257
|
+
@filtered_relation = ActiveRecordProxy.map_response(@relation, @search_definition.body, response)
|
282
258
|
end
|
283
259
|
end
|
284
260
|
|
@@ -302,5 +278,51 @@ module Elasticity
|
|
302
278
|
documents.public_send(method_name, *args, &block)
|
303
279
|
end
|
304
280
|
end
|
281
|
+
|
282
|
+
class Results < ActiveSupport::ProxyObject
|
283
|
+
include ::Enumerable
|
284
|
+
|
285
|
+
delegate :each, :size, :length, :[], :+, :-, :&, :|, to: :@documents
|
286
|
+
|
287
|
+
DEFAULT_SIZE = 10
|
288
|
+
|
289
|
+
def initialize(response, body, mapper = nil)
|
290
|
+
@response = response
|
291
|
+
@body = body
|
292
|
+
@documents = if mapper.nil?
|
293
|
+
@response["hits"]["hits"]
|
294
|
+
else
|
295
|
+
@response["hits"]["hits"].map { |hit| mapper.(hit) }
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
def method_missing(name, *args, &block)
|
300
|
+
@documents.public_send(name, *args, &block)
|
301
|
+
end
|
302
|
+
|
303
|
+
def each(&block)
|
304
|
+
@documents.each(&block)
|
305
|
+
end
|
306
|
+
|
307
|
+
def total
|
308
|
+
@response["hits"]["total"]
|
309
|
+
end
|
310
|
+
|
311
|
+
# for pagination
|
312
|
+
def per_page
|
313
|
+
@body[:size] || DEFAULT_SIZE
|
314
|
+
end
|
315
|
+
|
316
|
+
# for pagination
|
317
|
+
def total_pages
|
318
|
+
(total.to_f / per_page.to_f).ceil
|
319
|
+
end
|
320
|
+
|
321
|
+
# for pagination
|
322
|
+
def current_page
|
323
|
+
return 1 if @body[:from].nil?
|
324
|
+
@body[:from] / per_page + 1
|
325
|
+
end
|
326
|
+
end
|
305
327
|
end
|
306
328
|
end
|
data/lib/elasticity/version.rb
CHANGED
@@ -31,15 +31,18 @@ RSpec.describe Elasticity::MultiSearch do
|
|
31
31
|
end
|
32
32
|
|
33
33
|
it "performs multi search" do
|
34
|
-
subject.add(:first, Elasticity::Search::Facade.new(client, Elasticity::Search::Definition.new("index_first", "document_first", { search: :first })), documents: klass)
|
34
|
+
subject.add(:first, Elasticity::Search::Facade.new(client, Elasticity::Search::Definition.new("index_first", "document_first", { search: :first, size: 2 })), documents: klass)
|
35
35
|
subject.add(:second, Elasticity::Search::Facade.new(client, Elasticity::Search::Definition.new("index_second", "document_second", { search: :second })), documents: klass)
|
36
36
|
|
37
37
|
expect(Elasticity.config.client).to receive(:msearch).with(body: [
|
38
|
-
{ index: "index_first", type: "document_first", search: { search: :first } },
|
38
|
+
{ index: "index_first", type: "document_first", search: { search: :first, size: 2 } },
|
39
39
|
{ index: "index_second", type: "document_second", search: { search: :second } },
|
40
40
|
]).and_return(response)
|
41
41
|
|
42
|
-
expect(Array(subject[:first])).
|
43
|
-
expect(Array(subject[:second])).
|
42
|
+
expect(Array(subject[:first])).to eq [klass.new(_id: 1, name: "foo"), klass.new(_id: 2, name: "bar")]
|
43
|
+
expect(Array(subject[:second])).to eq [klass.new(_id: 3, name: "baz")]
|
44
|
+
expect(subject[:first].total).to eq 2
|
45
|
+
expect(subject[:first].total_pages).to eq 1
|
46
|
+
expect(subject[:first].current_page).to eq 1
|
44
47
|
end
|
45
48
|
end
|
data/spec/units/search_spec.rb
CHANGED
@@ -132,6 +132,7 @@ RSpec.describe "Search" do
|
|
132
132
|
klass: double(:klass, primary_key: "id"),
|
133
133
|
to_sql: "SELECT * FROM table_name WHERE id IN (1)"
|
134
134
|
)
|
135
|
+
|
135
136
|
allow(relation.connection).to receive(:quote_column_name) { |name| name }
|
136
137
|
allow(relation.connection).to receive(:quote) { |name| name }
|
137
138
|
|
@@ -167,7 +168,7 @@ RSpec.describe "Search" do
|
|
167
168
|
index: index_name,
|
168
169
|
type: document_type,
|
169
170
|
body: { size: 14, from: 25, filter: {} }
|
170
|
-
).and_return({ "hits" => { "total" => 112 } })
|
171
|
+
).and_return({ "hits" => { "total" => 112, "hits" => [] } })
|
171
172
|
docs = subject.documents(mapper)
|
172
173
|
|
173
174
|
expect(docs.per_page).to eq(14)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: es-elasticity
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rodrigo Kochenburger
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-02-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -230,7 +230,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
230
230
|
version: '0'
|
231
231
|
requirements: []
|
232
232
|
rubyforge_project:
|
233
|
-
rubygems_version: 2.4.5
|
233
|
+
rubygems_version: 2.4.5
|
234
234
|
signing_key:
|
235
235
|
specification_version: 4
|
236
236
|
summary: ActiveModel-based library for working with Elasticsearch
|
@@ -243,3 +243,4 @@ test_files:
|
|
243
243
|
- spec/units/multi_search_spec.rb
|
244
244
|
- spec/units/search_spec.rb
|
245
245
|
- spec/units/strategies/single_index_spec.rb
|
246
|
+
has_rdoc:
|