elastictastic 0.10.9 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
@@ -6,28 +6,54 @@ module Elastictastic
|
|
6
6
|
|
7
7
|
module ClassMethods
|
8
8
|
|
9
|
-
def create_or_update(
|
9
|
+
def create_or_update(*ids, &block)
|
10
10
|
scope = current_scope
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
11
|
+
ids.each do |id|
|
12
|
+
begin
|
13
|
+
new.tap do |instance|
|
14
|
+
instance.id = id
|
15
|
+
yield instance
|
16
|
+
end.create do |e|
|
17
|
+
case e
|
18
|
+
when nil # chill
|
19
|
+
when Elastictastic::ServerError::DocumentAlreadyExistsEngineException,
|
20
|
+
Elastictastic::ServerError::DocumentAlreadyExistsException # 0.19+
|
21
|
+
scope.update(id, &block)
|
22
|
+
else
|
23
|
+
raise e
|
24
|
+
end
|
25
|
+
end
|
26
|
+
rescue Elastictastic::CancelSave
|
27
|
+
# Do Nothing
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def update(*ids, &block)
|
33
|
+
[].tap do |found|
|
34
|
+
case ids.length
|
35
|
+
when 0 then return
|
36
|
+
when 1
|
37
|
+
id = ids.first
|
38
|
+
instance = scoped({}).find_one(id, :preference => '_primary_first')
|
39
|
+
return unless instance
|
40
|
+
found << id
|
41
|
+
instances = [instance]
|
20
42
|
else
|
21
|
-
|
43
|
+
instances = scoped({}).
|
44
|
+
find_many(ids, :preference => '_primary_first')
|
45
|
+
found.concat(instances.map { |instance| instance.id })
|
46
|
+
end
|
47
|
+
instances.each do |instance|
|
48
|
+
instance.try_update(current_scope, &block)
|
22
49
|
end
|
23
50
|
end
|
24
|
-
rescue Elastictastic::CancelSave
|
25
|
-
# Do Nothing
|
26
51
|
end
|
27
52
|
|
28
|
-
def
|
29
|
-
|
30
|
-
|
53
|
+
def update_or_create(*ids, &block)
|
54
|
+
updated_ids = update(*ids, &block)
|
55
|
+
create_ids = ids - updated_ids
|
56
|
+
create_or_update(*create_ids, &block) if create_ids.any?
|
31
57
|
end
|
32
58
|
|
33
59
|
def update_each(&block)
|
data/lib/elastictastic/scope.rb
CHANGED
@@ -282,6 +282,19 @@ module Elastictastic
|
|
282
282
|
end
|
283
283
|
end
|
284
284
|
|
285
|
+
#
|
286
|
+
# @private
|
287
|
+
#
|
288
|
+
def find_many(ids, params = {})
|
289
|
+
docspec = ids.map do |id|
|
290
|
+
{ '_id' => id }.merge!(params_for_find_many).
|
291
|
+
merge!(params.stringify_keys)
|
292
|
+
end
|
293
|
+
materialize_hits(
|
294
|
+
::Elastictastic.client.mget(docspec, index, type)['docs']
|
295
|
+
).map { |result, hit| result }
|
296
|
+
end
|
297
|
+
|
285
298
|
def multi_get_params
|
286
299
|
{
|
287
300
|
'_type' => type,
|
@@ -380,16 +393,6 @@ module Elastictastic
|
|
380
393
|
self.counts = search(params)
|
381
394
|
end
|
382
395
|
|
383
|
-
def find_many(ids, params = {})
|
384
|
-
docspec = ids.map do |id|
|
385
|
-
{ '_id' => id }.merge!(params_for_find_many).
|
386
|
-
merge!(params.stringify_keys)
|
387
|
-
end
|
388
|
-
materialize_hits(
|
389
|
-
::Elastictastic.client.mget(docspec, index, type)['docs']
|
390
|
-
).map { |result, hit| result }
|
391
|
-
end
|
392
|
-
|
393
396
|
def params_for_find_one
|
394
397
|
params_for_find.tap do |params|
|
395
398
|
params['fields'] &&= params['fields'].join(',')
|
@@ -113,6 +113,52 @@ describe Elastictastic::OptimisticLocking do
|
|
113
113
|
end
|
114
114
|
end # describe '::update'
|
115
115
|
|
116
|
+
describe '::update with multiple arguments' do
|
117
|
+
let(:last_update_request) do
|
118
|
+
FakeWeb.requests.reverse.find { |req| req.method == 'PUT' }
|
119
|
+
end
|
120
|
+
|
121
|
+
before do
|
122
|
+
stub_es_mget(
|
123
|
+
index,
|
124
|
+
'post',
|
125
|
+
'1' => {},
|
126
|
+
'2' => {}
|
127
|
+
)
|
128
|
+
stub_es_get(index, 'post', '2', { :title => 'Hey' }, 2)
|
129
|
+
stub_es_update(index, 'post', '1')
|
130
|
+
stub_request_json(
|
131
|
+
:put,
|
132
|
+
match_es_resource(index, 'post', '2'),
|
133
|
+
version_conflict,
|
134
|
+
generate_es_hit('post', :id => '2', :index => index, :version => 3)
|
135
|
+
)
|
136
|
+
scope.update('1', '2') do |post|
|
137
|
+
post.comments_count = 2
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'should retry unsuccessful updates' do
|
142
|
+
FakeWeb.should have(5).requests # mget, update '1', update '2' (fail), get '2', update '2'
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'should re-perform update on failed document' do
|
146
|
+
URI.parse(last_update_request.path).path.should == "/#{index}/post/2"
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'should send data from latest version in persistence' do
|
150
|
+
Elastictastic.json_decode(last_update_request.body)['title'].should == 'Hey'
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'should send data from update block' do
|
154
|
+
Elastictastic.json_decode(last_update_request.body)['comments_count'].should == 2
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'should update with latest version' do
|
158
|
+
URI.parse(last_update_request.path).query.split('&').should include('version=2')
|
159
|
+
end
|
160
|
+
end # describe '::update with multiple requests'
|
161
|
+
|
116
162
|
describe '::update_each' do
|
117
163
|
let(:last_update_request) do
|
118
164
|
FakeWeb.requests.reverse.find { |req| req.method == 'PUT' }
|
@@ -383,6 +429,46 @@ describe Elastictastic::OptimisticLocking do
|
|
383
429
|
last_request_json['title'].should == 'hey'
|
384
430
|
end
|
385
431
|
end
|
432
|
+
|
433
|
+
context "with multiple arguments some of which exist" do
|
434
|
+
before do
|
435
|
+
stub_es_create('my_index', 'post', '1')
|
436
|
+
stub_request_json(
|
437
|
+
:put,
|
438
|
+
match_es_path('/my_index/post/2/_create'),
|
439
|
+
already_exists
|
440
|
+
)
|
441
|
+
stub_es_get('my_index', 'post', '2', :comments_count => 2)
|
442
|
+
stub_es_update('my_index', 'post', '2')
|
443
|
+
Post.in_index('my_index').create_or_update('1', '2') do |post|
|
444
|
+
post.title = "hey #{post.id}"
|
445
|
+
end
|
446
|
+
end
|
447
|
+
|
448
|
+
it 'should post to create endpoint for both documents' do
|
449
|
+
FakeWeb.requests.
|
450
|
+
should be_any { |request| request.path == '/my_index/post/1/_create' }
|
451
|
+
FakeWeb.requests.
|
452
|
+
should be_any { |request| request.path == '/my_index/post/2/_create' }
|
453
|
+
end
|
454
|
+
|
455
|
+
it 'should not send update request for successful create' do
|
456
|
+
FakeWeb.requests.
|
457
|
+
should_not be_any { |request| request.path == '/my_index/post/1?version=1' }
|
458
|
+
end
|
459
|
+
|
460
|
+
it 'should re-update existing data with correct version' do
|
461
|
+
last_request.path.should == '/my_index/post/2?version=1'
|
462
|
+
end
|
463
|
+
|
464
|
+
it 'should include data from storage' do
|
465
|
+
last_request_json['comments_count'].should == 2
|
466
|
+
end
|
467
|
+
|
468
|
+
it 'should include updated data from block' do
|
469
|
+
last_request_json['title'].should == 'hey 2'
|
470
|
+
end
|
471
|
+
end
|
386
472
|
end
|
387
473
|
|
388
474
|
context 'with bulk persistence' do
|
@@ -413,4 +499,44 @@ describe Elastictastic::OptimisticLocking do
|
|
413
499
|
end
|
414
500
|
end
|
415
501
|
end
|
502
|
+
|
503
|
+
describe '::update_or_create' do
|
504
|
+
let(:scope) { Post }
|
505
|
+
|
506
|
+
before do
|
507
|
+
stub_es_mget(
|
508
|
+
'default', 'post',
|
509
|
+
'1' => {title: 'Post 1'},
|
510
|
+
'2' => nil
|
511
|
+
)
|
512
|
+
stub_es_update('default', 'post', '1')
|
513
|
+
stub_es_create('default', 'post', '2')
|
514
|
+
scope.update_or_create('1', '2') do |post|
|
515
|
+
post.comments_count = 1
|
516
|
+
end
|
517
|
+
end
|
518
|
+
|
519
|
+
let :create_request do
|
520
|
+
FakeWeb.requests.
|
521
|
+
find { |request| request.path == "/default/post/2/_create" }
|
522
|
+
end
|
523
|
+
|
524
|
+
let :update_request do
|
525
|
+
FakeWeb.requests.
|
526
|
+
find { |request| request.path =~ %r(^/default/post/1\??) }
|
527
|
+
end
|
528
|
+
|
529
|
+
it 'should not send any extraneous requests' do
|
530
|
+
FakeWeb.should have(3).requests # multiget, create, update
|
531
|
+
end
|
532
|
+
|
533
|
+
it 'should send create request for nonexistent document' do
|
534
|
+
create_request.should be
|
535
|
+
end
|
536
|
+
|
537
|
+
it 'should send update request for existent document' do
|
538
|
+
update_request.should be
|
539
|
+
end
|
540
|
+
end
|
541
|
+
|
416
542
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: elastictastic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2013-
|
14
|
+
date: 2013-03-28 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: activesupport
|
@@ -250,7 +250,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
250
250
|
requirements:
|
251
251
|
- ElasticSearch
|
252
252
|
rubyforge_project:
|
253
|
-
rubygems_version: 1.8.
|
253
|
+
rubygems_version: 1.8.25
|
254
254
|
signing_key:
|
255
255
|
specification_version: 3
|
256
256
|
summary: Object-document mapper for ElasticSearch
|