tire 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +0 -31
- data/lib/tire.rb +1 -0
- data/lib/tire/index.rb +58 -5
- data/lib/tire/version.rb +4 -1
- data/test/integration/bulk_test.rb +81 -0
- data/test/models/mongoid_models.rb +0 -12
- data/test/test_helper.rb +11 -1
- data/test/unit/index_test.rb +148 -43
- data/test/unit/rubyext_test.rb +1 -1
- data/tire.gemspec +2 -7
- metadata +54 -50
data/Rakefile
CHANGED
@@ -24,37 +24,6 @@ namespace :test do
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
# Generate documentation
|
28
|
-
begin
|
29
|
-
require 'rdoc'
|
30
|
-
require 'rdoc/task'
|
31
|
-
Rake::RDocTask.new do |rdoc|
|
32
|
-
rdoc.rdoc_dir = 'rdoc'
|
33
|
-
rdoc.title = "Tire"
|
34
|
-
rdoc.rdoc_files.include('README.markdown')
|
35
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
36
|
-
end
|
37
|
-
rescue LoadError
|
38
|
-
task :rdoc do
|
39
|
-
abort "[!] RDoc gem is not available."
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
# Generate coverage reports
|
44
|
-
begin
|
45
|
-
require 'rcov/rcovtask'
|
46
|
-
Rcov::RcovTask.new do |test|
|
47
|
-
test.libs << 'test'
|
48
|
-
test.rcov_opts = ['--exclude', 'gems/*']
|
49
|
-
test.pattern = 'test/**/*_test.rb'
|
50
|
-
test.verbose = true
|
51
|
-
end
|
52
|
-
rescue LoadError
|
53
|
-
task :rcov do
|
54
|
-
abort "[!] RCov gem is not available."
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
27
|
namespace :web do
|
59
28
|
|
60
29
|
desc "Update the Github website"
|
data/lib/tire.rb
CHANGED
@@ -11,6 +11,7 @@ require 'active_support/core_ext/hash/except.rb'
|
|
11
11
|
# Ruby 1.8 compatibility
|
12
12
|
require 'tire/rubyext/ruby_1_8' if defined?(RUBY_VERSION) && RUBY_VERSION < '1.9'
|
13
13
|
|
14
|
+
require 'tire/version'
|
14
15
|
require 'tire/rubyext/hash'
|
15
16
|
require 'tire/rubyext/symbol'
|
16
17
|
require 'tire/utils'
|
data/lib/tire/index.rb
CHANGED
@@ -90,16 +90,50 @@ module Tire
|
|
90
90
|
logged([type, id].join('/'), curl)
|
91
91
|
end
|
92
92
|
|
93
|
-
|
93
|
+
# Performs a [multi-search](http://www.elasticsearch.org/guide/reference/api/bulk.html) request
|
94
|
+
#
|
95
|
+
# @myindex.bulk :index, [ {id: 1, title: 'One'}, { id: 2, title: 'Two', _version: 3 } ], refresh: true
|
96
|
+
#
|
97
|
+
# Pass the action (`index`, `create`, `delete`) as the first argument, the collection of documents as
|
98
|
+
# the second argument, and URL parameters as the last option.
|
99
|
+
#
|
100
|
+
# Any _meta_ information contained in documents (such as `_routing` or `_parent`) is extracted
|
101
|
+
# and added to the "header" line.
|
102
|
+
#
|
103
|
+
# Shortcut methods `bulk_store`, `bulk_delete` and `bulk_create` are available.
|
104
|
+
#
|
105
|
+
def bulk(action, documents, options={})
|
106
|
+
# TODO: A more Ruby-like DSL notation should be supported:
|
107
|
+
#
|
108
|
+
# Tire.index('myindex').bulk do
|
109
|
+
# create id: 1, title: 'bar', _routing: 'abc'
|
110
|
+
# delete id: 1
|
111
|
+
# # ...
|
112
|
+
# end
|
113
|
+
#
|
94
114
|
payload = documents.map do |document|
|
95
115
|
type = get_type_from_document(document, :escape => false) # Do not URL-escape the _type
|
96
116
|
id = get_id_from_document(document)
|
97
117
|
|
98
118
|
STDERR.puts "[ERROR] Document #{document.inspect} does not have ID" unless id
|
99
119
|
|
120
|
+
header = { action.to_sym => { :_index => name, :_type => type, :_id => id } }
|
121
|
+
|
122
|
+
if document.respond_to?(:to_hash) && hash = document.to_hash
|
123
|
+
meta = {}
|
124
|
+
meta[:_version] = hash.delete(:_version)
|
125
|
+
meta[:_routing] = hash.delete(:_routing)
|
126
|
+
meta[:_percolate] = hash.delete(:_percolate)
|
127
|
+
meta[:_parent] = hash.delete(:_parent)
|
128
|
+
meta[:_timestamp] = hash.delete(:_timestamp)
|
129
|
+
meta[:_ttl] = hash.delete(:_ttl)
|
130
|
+
meta = meta.reject { |name,value| !value || value.empty? }
|
131
|
+
header[action.to_sym].update(meta)
|
132
|
+
end
|
133
|
+
|
100
134
|
output = []
|
101
|
-
output <<
|
102
|
-
output << convert_document_to_json(document)
|
135
|
+
output << MultiJson.encode(header)
|
136
|
+
output << convert_document_to_json(document) unless action.to_s == 'delete'
|
103
137
|
output.join("\n")
|
104
138
|
end
|
105
139
|
payload << ""
|
@@ -108,7 +142,13 @@ module Tire
|
|
108
142
|
count = 0
|
109
143
|
|
110
144
|
begin
|
111
|
-
|
145
|
+
params = {}
|
146
|
+
params[:consistency] = options.delete(:consistency)
|
147
|
+
params[:refresh] = options.delete(:refresh)
|
148
|
+
params = params.reject { |name,value| !value }
|
149
|
+
params_encoded = params.empty? ? '' : "?#{params.to_param}"
|
150
|
+
|
151
|
+
@response = Configuration.client.post("#{url}/_bulk#{params_encoded}", payload.join("\n"))
|
112
152
|
raise RuntimeError, "#{@response.code} > #{@response.body}" if @response && @response.failure?
|
113
153
|
@response
|
114
154
|
rescue StandardError => error
|
@@ -123,8 +163,21 @@ module Tire
|
|
123
163
|
|
124
164
|
ensure
|
125
165
|
curl = %Q|curl -X POST "#{url}/_bulk" --data-binary '{... data omitted ...}'|
|
126
|
-
logged('
|
166
|
+
logged('_bulk', curl)
|
127
167
|
end
|
168
|
+
|
169
|
+
end
|
170
|
+
|
171
|
+
def bulk_create(documents, options={})
|
172
|
+
bulk :create, documents, options
|
173
|
+
end
|
174
|
+
|
175
|
+
def bulk_store(documents, options={})
|
176
|
+
bulk :index, documents, options
|
177
|
+
end
|
178
|
+
|
179
|
+
def bulk_delete(documents, options={})
|
180
|
+
bulk :delete, documents, options
|
128
181
|
end
|
129
182
|
|
130
183
|
def import(klass_or_collection, options={})
|
data/lib/tire/version.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Tire
|
2
|
-
VERSION = "0.5.
|
2
|
+
VERSION = "0.5.1"
|
3
3
|
|
4
4
|
CHANGELOG =<<-END
|
5
5
|
IMPORTANT CHANGES LATELY:
|
@@ -29,5 +29,8 @@ module Tire
|
|
29
29
|
* Added a `match` query type
|
30
30
|
* Added support for multisearch (_msearch) and the `Tire.multi_search` DSL method
|
31
31
|
* Added support for multi-search in the ActiveModel integration and in Tire::Model::Persistence
|
32
|
+
* Added support for create and delete actions for Index#bulk
|
33
|
+
* Added support for meta information (`_routing`, `_parent`, etc) in Index#bulk
|
34
|
+
* Added support for URL parameters (`refresh`, `consistency`) in Index#bulk
|
32
35
|
END
|
33
36
|
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Tire
|
4
|
+
|
5
|
+
class BulkIntegrationTest < Test::Unit::TestCase
|
6
|
+
include Test::Integration
|
7
|
+
|
8
|
+
context "Bulk" do
|
9
|
+
setup do
|
10
|
+
@index = Tire.index('bulk-test') { delete; create }
|
11
|
+
@articles = [
|
12
|
+
{ id: '1', type: 'article', title: 'one', tags: ['ruby'] },
|
13
|
+
{ id: '2', type: 'article', title: 'two', tags: ['ruby', 'python'] },
|
14
|
+
{ id: '3', type: 'article', title: 'three', tags: ['java'] }
|
15
|
+
]
|
16
|
+
end
|
17
|
+
|
18
|
+
teardown do
|
19
|
+
@index.delete
|
20
|
+
Tire.index('bulk-test-fresh').delete
|
21
|
+
end
|
22
|
+
|
23
|
+
should "store a collection of documents and refresh the index" do
|
24
|
+
@index.bulk_store @articles, refresh: true
|
25
|
+
assert_equal 3, Tire.search('bulk-test/article').query { all }.results.size
|
26
|
+
end
|
27
|
+
|
28
|
+
should "extract the routing value from documents" do
|
29
|
+
@index.bulk_store [ { id: '1', title: 'A', _routing: 'a'}, { id: '2', title: 'B', _routing: 'b'} ]
|
30
|
+
@index.refresh
|
31
|
+
|
32
|
+
assert_equal 2, Tire.search('bulk-test') { query {all} }.results.size
|
33
|
+
assert_equal 1, Tire.search('bulk-test', routing: 'a') { query {all} }.results.size
|
34
|
+
assert_equal 1, Tire.search('bulk-test', routing: 'b') { query {all} }.results.size
|
35
|
+
end
|
36
|
+
|
37
|
+
should "delete documents in bulk" do
|
38
|
+
(1..10).to_a.each { |i| @index.store id: i }
|
39
|
+
@index.refresh
|
40
|
+
assert_equal 10, Tire.search('bulk-test') { query {all} }.results.size
|
41
|
+
|
42
|
+
documents = (1..10).to_a.map { |i| { id: i } }
|
43
|
+
@index.bulk_delete documents, refresh: true
|
44
|
+
assert_equal 0, Tire.search('bulk-test') { query {all} }.results.size
|
45
|
+
end
|
46
|
+
|
47
|
+
should "allow to feed search results to bulk API" do
|
48
|
+
(1..10).to_a.each { |i| @index.store id: i }
|
49
|
+
@index.refresh
|
50
|
+
assert_equal 10, Tire.search('bulk-test') { query {all} }.results.size
|
51
|
+
|
52
|
+
documents = Tire.search('bulk-test') { query {all} }.results.to_a
|
53
|
+
|
54
|
+
@index.bulk_delete documents, refresh: true
|
55
|
+
assert_equal 0, Tire.search('bulk-test') { query {all} }.results.size
|
56
|
+
|
57
|
+
Tire.index('bulk-test-fresh').bulk_create documents, refresh: true
|
58
|
+
assert_equal 10, Tire.search('bulk-test-fresh') { query {all} }.results.size
|
59
|
+
end
|
60
|
+
|
61
|
+
should "timeout when consistency factor is not met" do
|
62
|
+
# Tire.configure { logger STDERR, level: 'debug' }
|
63
|
+
|
64
|
+
Tire.index 'bulk-test' do
|
65
|
+
delete
|
66
|
+
create index: { number_of_shards: 1, number_of_replicas: 15 }
|
67
|
+
end
|
68
|
+
|
69
|
+
assert_raise Timeout::Error do
|
70
|
+
Timeout::timeout(3) do
|
71
|
+
Tire.index('bulk-test').bulk_store [ {id: '1', title: 'One' } ],
|
72
|
+
consistency: 'all',
|
73
|
+
raise: true
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
@@ -8,14 +8,6 @@ class MongoidArticle
|
|
8
8
|
has_many :comments, :class_name => "MongoidComment", :foreign_key => "article_id"
|
9
9
|
has_many :stats, :class_name => "MongoidStat", :foreign_key => "article_id"
|
10
10
|
|
11
|
-
# def index
|
12
|
-
# "KEEP OFF MY INDEX!!!"
|
13
|
-
# end
|
14
|
-
#
|
15
|
-
# def self.settings
|
16
|
-
# "KEEP OFF MY SETTINGS!!!"
|
17
|
-
# end
|
18
|
-
|
19
11
|
include Tire::Model::Search
|
20
12
|
include Tire::Model::Callbacks
|
21
13
|
|
@@ -31,10 +23,6 @@ class MongoidArticle
|
|
31
23
|
end
|
32
24
|
end
|
33
25
|
|
34
|
-
# tire.mapping do
|
35
|
-
# indexes :title, :type => 'string', :boost => 10, :analyzer => 'snowball'
|
36
|
-
# end
|
37
|
-
|
38
26
|
def to_indexed_json
|
39
27
|
{
|
40
28
|
:title => title,
|
data/test/test_helper.rb
CHANGED
@@ -4,7 +4,12 @@ require 'bundler/setup'
|
|
4
4
|
require 'pathname'
|
5
5
|
require 'test/unit'
|
6
6
|
|
7
|
-
|
7
|
+
if ENV['JSON_LIBRARY']
|
8
|
+
puts "Using '#{ENV['JSON_LIBRARY']}' JSON library"
|
9
|
+
require ENV['JSON_LIBRARY']
|
10
|
+
else
|
11
|
+
require 'yajl/json_gem'
|
12
|
+
end
|
8
13
|
require 'sqlite3'
|
9
14
|
|
10
15
|
require 'shoulda'
|
@@ -14,6 +19,11 @@ require 'mocha'
|
|
14
19
|
require 'active_support/core_ext/hash/indifferent_access'
|
15
20
|
|
16
21
|
require 'tire'
|
22
|
+
if ENV['CURB']
|
23
|
+
puts "Using 'curb' as the HTTP library"
|
24
|
+
require 'tire/http/clients/curb'
|
25
|
+
Tire.configure { client Tire::HTTP::Client::Curb }
|
26
|
+
end
|
17
27
|
|
18
28
|
# Require basic model files
|
19
29
|
#
|
data/test/unit/index_test.rb
CHANGED
@@ -370,7 +370,7 @@ module Tire
|
|
370
370
|
|
371
371
|
should "allow to set routing" do
|
372
372
|
Configuration.client.expects(:get).with("#{@index.url}/article/id-1?routing=foo").
|
373
|
-
returns(mock_response('{"_id":"id-1"'))
|
373
|
+
returns(mock_response('{"_id":"id-1"}'))
|
374
374
|
article = @index.retrieve :article, 'id-1', :routing => 'foo'
|
375
375
|
end
|
376
376
|
|
@@ -378,7 +378,7 @@ module Tire
|
|
378
378
|
Configuration.client.expects(:get).with do |url|
|
379
379
|
assert url.include?('routing=foo'), url
|
380
380
|
assert url.include?('fields=name'), url
|
381
|
-
end.returns(mock_response('{"_id":"id-1"'))
|
381
|
+
end.returns(mock_response('{"_id":"id-1"}'))
|
382
382
|
|
383
383
|
article = @index.retrieve :article, 'id-1', :routing => 'foo', :fields => 'name'
|
384
384
|
end
|
@@ -386,7 +386,7 @@ module Tire
|
|
386
386
|
should "allow to set preference" do
|
387
387
|
Configuration.client.expects(:get).with do |url|
|
388
388
|
assert url.include?('preference=foo'), url
|
389
|
-
end.returns(mock_response('{"_id":"id-1"'))
|
389
|
+
end.returns(mock_response('{"_id":"id-1"}'))
|
390
390
|
|
391
391
|
article = @index.retrieve :article, 'id-1', :preference => 'foo'
|
392
392
|
end
|
@@ -490,56 +490,159 @@ module Tire
|
|
490
490
|
|
491
491
|
end
|
492
492
|
|
493
|
-
context "when
|
493
|
+
context "when performing a bulk api action" do
|
494
|
+
# Possible Bulk API actions are `index`, `create`, `delete`
|
495
|
+
#
|
494
496
|
# The expected JSON looks like this:
|
495
497
|
#
|
496
498
|
# {"index":{"_index":"dummy","_type":"document","_id":"1"}}
|
497
499
|
# {"id":"1","title":"One"}
|
498
|
-
# {"
|
500
|
+
# {"create":{"_index":"dummy","_type":"document","_id":"2"}}
|
499
501
|
# {"id":"2","title":"Two"}
|
502
|
+
# {"delete":{"_index":"dummy","_type":"document","_id":"2"}}
|
500
503
|
#
|
501
504
|
# See http://www.elasticsearch.org/guide/reference/api/bulk.html
|
502
505
|
|
503
|
-
should "serialize
|
504
|
-
Configuration.client.
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
506
|
+
should "serialize payload for index action" do
|
507
|
+
Configuration.client.
|
508
|
+
expects(:post).
|
509
|
+
with do |url, payload|
|
510
|
+
assert_equal "#{@index.url}/_bulk", url
|
511
|
+
assert_match /"index"/, payload
|
512
|
+
assert_match /"_index":"dummy"/, payload
|
513
|
+
assert_match /"_type":"document"/, payload
|
514
|
+
assert_match /"_id":"1"/, payload
|
515
|
+
assert_match /"_id":"2"/, payload
|
516
|
+
assert_match /"title":"One"/, payload
|
517
|
+
assert_match /"title":"Two"/, payload
|
518
|
+
end.
|
519
|
+
returns(mock_response('{}'), 200)
|
515
520
|
|
516
|
-
@index.
|
521
|
+
@index.bulk :index, [ {:id => '1', :title => 'One'}, {:id => '2', :title => 'Two'} ]
|
517
522
|
end
|
518
523
|
|
519
|
-
should "serialize
|
520
|
-
Configuration.client.
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
524
|
+
should "serialize payload for create action" do
|
525
|
+
Configuration.client.
|
526
|
+
expects(:post).
|
527
|
+
with do |url, payload|
|
528
|
+
assert_equal "#{@index.url}/_bulk", url
|
529
|
+
assert_match /"create"/, payload
|
530
|
+
assert_match /"_index":"dummy"/, payload
|
531
|
+
assert_match /"_type":"document"/, payload
|
532
|
+
assert_match /"_id":"1"/, payload
|
533
|
+
assert_match /"_id":"2"/, payload
|
534
|
+
assert_match /"title":"One"/, payload
|
535
|
+
assert_match /"title":"Two"/, payload
|
536
|
+
end.
|
537
|
+
returns(mock_response('{}'), 200)
|
538
|
+
|
539
|
+
@index.bulk :create, [ {:id => '1', :title => 'One'}, {:id => '2', :title => 'Two'} ]
|
540
|
+
end
|
541
|
+
|
542
|
+
should "serialize payload for delete action" do
|
543
|
+
Configuration.client.
|
544
|
+
expects(:post).
|
545
|
+
with do |url, payload|
|
546
|
+
assert_equal "#{@index.url}/_bulk", url
|
547
|
+
assert_match /"delete"/, payload
|
548
|
+
assert_match /"_index":"dummy"/, payload
|
549
|
+
assert_match /"_type":"document"/, payload
|
550
|
+
assert_match /"_id":"1"/, payload
|
551
|
+
assert_match /"_id":"2"/, payload
|
552
|
+
assert ! payload.include?('"title"')
|
553
|
+
end.
|
554
|
+
returns(mock_response('{}'), 200)
|
555
|
+
|
556
|
+
@index.bulk :delete, [ {:id => '1', :title => 'One'}, {:id => '2', :title => 'Two'} ]
|
557
|
+
end
|
558
|
+
|
559
|
+
should "serialize meta parameters such as routing into payload header" do
|
560
|
+
Configuration.client.
|
561
|
+
expects(:post).
|
562
|
+
with do |url, payload|
|
563
|
+
# print payload
|
564
|
+
lines = payload.split("\n")
|
565
|
+
assert_match /"_routing":"A"/, lines[0]
|
566
|
+
assert_match /"_routing":"B"/, lines[2]
|
567
|
+
assert_match /"_ttl":"1d"/, lines[2]
|
568
|
+
assert ! lines[4].include?('"_routing"')
|
569
|
+
end.
|
570
|
+
returns(mock_response('{}'), 200)
|
571
|
+
|
572
|
+
@index.bulk :index,
|
573
|
+
[
|
574
|
+
{:id => '1', :title => 'One', :_routing => 'A'},
|
575
|
+
{:id => '2', :title => 'Two', :_routing => 'B', :_ttl => '1d'},
|
576
|
+
{:id => '3', :title => 'Three'}
|
577
|
+
]
|
578
|
+
|
579
|
+
end
|
580
|
+
|
581
|
+
should "pass URL parameters such as refresh or consistency" do
|
582
|
+
Configuration.client.
|
583
|
+
expects(:post).
|
584
|
+
with do |url, payload|
|
585
|
+
# p url
|
586
|
+
assert_match /\?consistency=one/, url
|
587
|
+
assert_match /&refresh=true/, url
|
588
|
+
end.
|
589
|
+
returns(mock_response('{}'), 200)
|
590
|
+
|
591
|
+
@index.bulk :index,
|
592
|
+
[ {:id => '1', :title => 'One' } ],
|
593
|
+
:consistency => 'one',
|
594
|
+
:refresh => true
|
595
|
+
|
596
|
+
end
|
597
|
+
|
598
|
+
should "serialize ActiveModel instances as payload" do
|
599
|
+
Configuration.client.
|
600
|
+
expects(:post).
|
601
|
+
with do |url, payload|
|
602
|
+
assert_equal "#{ActiveModelArticle.index.url}/_bulk", url
|
603
|
+
assert_match /"index"/, payload
|
604
|
+
assert_match /"_index":"active_model_articles"/, payload
|
605
|
+
assert_match /"_type":"active_model_article"/, payload
|
606
|
+
assert_match /"_id":"1"/, payload
|
607
|
+
assert_match /"_id":"2"/, payload
|
608
|
+
assert_match /"title":"One"/, payload
|
609
|
+
assert_match /"title":"Two"/, payload
|
610
|
+
end.
|
611
|
+
returns(mock_response('{}'), 200)
|
529
612
|
|
530
613
|
one = ActiveModelArticle.new 'title' => 'One'; one.id = '1'
|
531
614
|
two = ActiveModelArticle.new 'title' => 'Two'; two.id = '2'
|
532
615
|
|
533
|
-
ActiveModelArticle.index.
|
616
|
+
ActiveModelArticle.index.bulk :index, [ one, two ]
|
534
617
|
end
|
535
618
|
|
536
|
-
|
619
|
+
should "extract meta information from document objects" do
|
620
|
+
Configuration.client.
|
621
|
+
expects(:post).
|
622
|
+
with do |url, payload|
|
623
|
+
print payload
|
624
|
+
lines = payload.split("\n")
|
625
|
+
assert_match /"_routing":"A"/, lines[0]
|
626
|
+
end.
|
627
|
+
returns(mock_response('{}'), 200)
|
628
|
+
|
629
|
+
class MyModel
|
630
|
+
def document_type; "my_model"; end
|
631
|
+
def to_hash; { :id => 1, :title => 'Foo', :_routing => 'A' }; end
|
632
|
+
def to_indexed_json; MultiJson.encode(to_hash); end
|
633
|
+
end
|
634
|
+
|
635
|
+
Tire.index('my_models').bulk_store [ MyModel.new ]
|
636
|
+
end
|
637
|
+
|
638
|
+
context "with namespaced models" do
|
639
|
+
|
537
640
|
should "not URL-escape the document_type" do
|
538
|
-
Configuration.client.expects(:post).with do |url,
|
539
|
-
# puts url,
|
540
|
-
|
541
|
-
|
542
|
-
|
641
|
+
Configuration.client.expects(:post).with do |url, payload|
|
642
|
+
# puts url, payload
|
643
|
+
assert_equal "#{Configuration.url}/my_namespace_my_models/_bulk", url
|
644
|
+
assert_match %r|"_index":"my_namespace_my_models"|, payload
|
645
|
+
assert_match %r|"_type":"my_namespace/my_model"|, payload
|
543
646
|
end.returns(mock_response('{}', 200))
|
544
647
|
|
545
648
|
module MyNamespace
|
@@ -549,35 +652,37 @@ module Tire
|
|
549
652
|
end
|
550
653
|
end
|
551
654
|
|
552
|
-
Tire.index('my_namespace_my_models').
|
655
|
+
Tire.index('my_namespace_my_models').bulk :index, [ MyNamespace::MyModel.new ]
|
553
656
|
end
|
554
657
|
end
|
555
658
|
|
556
659
|
should "try again when an exception occurs" do
|
557
660
|
Configuration.client.expects(:post).returns(mock_response('Server error', 503)).at_least(2)
|
558
661
|
|
559
|
-
assert !@index.
|
662
|
+
assert !@index.bulk(:index, [ {:id => '1', :title => 'One'}, {:id => '2', :title => 'Two'} ])
|
560
663
|
end
|
561
664
|
|
562
665
|
should "try again and the raise when an exception occurs" do
|
563
666
|
Configuration.client.expects(:post).returns(mock_response('Server error', 503)).at_least(2)
|
564
667
|
|
565
668
|
assert_raise(RuntimeError) do
|
566
|
-
@index.
|
669
|
+
@index.bulk :index,
|
670
|
+
[ {:id => '1', :title => 'One'}, {:id => '2', :title => 'Two'} ],
|
671
|
+
:raise => true
|
567
672
|
end
|
568
673
|
end
|
569
674
|
|
570
675
|
should "try again when a connection error occurs" do
|
571
676
|
Configuration.client.expects(:post).raises(Errno::ECONNREFUSED, "Connection refused - connect(2)").at_least(2)
|
572
677
|
|
573
|
-
assert !@index.
|
678
|
+
assert !@index.bulk(:index, [ {:id => '1', :title => 'One'} ])
|
574
679
|
end
|
575
680
|
|
576
|
-
should "
|
681
|
+
should "retry on SIGINT type of exceptions" do
|
577
682
|
Configuration.client.expects(:post).raises(Interrupt, "abort then interrupt!")
|
578
683
|
|
579
684
|
assert_raise Interrupt do
|
580
|
-
@index.
|
685
|
+
@index.bulk :index, [ {:id => '1', :title => 'One'} ]
|
581
686
|
end
|
582
687
|
end
|
583
688
|
|
@@ -589,7 +694,7 @@ module Tire
|
|
589
694
|
STDERR.expects(:puts).once
|
590
695
|
|
591
696
|
documents = [ { :title => 'Bogus' }, { :title => 'Real', :id => 1 } ]
|
592
|
-
ActiveModelArticle.index.
|
697
|
+
ActiveModelArticle.index.bulk :index, documents
|
593
698
|
end
|
594
699
|
|
595
700
|
should "log the response code" do
|
@@ -600,7 +705,7 @@ module Tire
|
|
600
705
|
status == 200
|
601
706
|
end
|
602
707
|
|
603
|
-
@index.
|
708
|
+
@index.bulk :index, [ {:id => '1', :title => 'One'} ]
|
604
709
|
end
|
605
710
|
|
606
711
|
end
|
data/test/unit/rubyext_test.rb
CHANGED
@@ -35,7 +35,7 @@ module Tire
|
|
35
35
|
end
|
36
36
|
|
37
37
|
should "have to_indexed_json method doing the same as to_json" do
|
38
|
-
[{}, {
|
38
|
+
[{}, { :foo => 2 }, { :foo => 4, :bar => 6 }, { :foo => [7,8,9] }].each do |h|
|
39
39
|
assert_equal MultiJson.decode(h.to_json), MultiJson.decode(h.to_indexed_json)
|
40
40
|
end
|
41
41
|
end
|
data/tire.gemspec
CHANGED
@@ -38,21 +38,16 @@ Gem::Specification.new do |s|
|
|
38
38
|
s.add_development_dependency "yajl-ruby", "~> 1.0"
|
39
39
|
s.add_development_dependency "shoulda"
|
40
40
|
s.add_development_dependency "mocha"
|
41
|
+
s.add_development_dependency "minitest", "~> 2.12"
|
41
42
|
s.add_development_dependency "activerecord", ">= 3.0"
|
42
43
|
s.add_development_dependency "sqlite3"
|
43
44
|
s.add_development_dependency "mongoid", "~> 2.2"
|
44
45
|
s.add_development_dependency "bson_ext"
|
45
46
|
s.add_development_dependency "redis-persistence"
|
46
47
|
s.add_development_dependency "curb"
|
47
|
-
s.add_development_dependency "
|
48
|
+
s.add_development_dependency "oj"
|
48
49
|
s.add_development_dependency "turn", "~> 0.9" if defined?(RUBY_VERSION) && RUBY_VERSION > '1.9'
|
49
50
|
|
50
|
-
# These gems are not needed for CI at <http://travis-ci.org/#!/karmi/tire>
|
51
|
-
#
|
52
|
-
unless ENV["CI"]
|
53
|
-
s.add_development_dependency "rdoc"
|
54
|
-
end
|
55
|
-
|
56
51
|
s.description = <<-DESC
|
57
52
|
Tire is a Ruby client for the ElasticSearch search engine/database.
|
58
53
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tire
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-11-
|
12
|
+
date: 2012-11-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
16
|
-
requirement: &
|
16
|
+
requirement: &70241536312360 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70241536312360
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rest-client
|
27
|
-
requirement: &
|
27
|
+
requirement: &70241536310740 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '1.6'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70241536310740
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: multi_json
|
38
|
-
requirement: &
|
38
|
+
requirement: &70241536309980 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '1.0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70241536309980
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: activemodel
|
49
|
-
requirement: &
|
49
|
+
requirement: &70241536309040 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '3.0'
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70241536309040
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: hashr
|
60
|
-
requirement: &
|
60
|
+
requirement: &70241536306480 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ~>
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: 0.0.19
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70241536306480
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: bundler
|
71
|
-
requirement: &
|
71
|
+
requirement: &70241536322700 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ~>
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '1.0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70241536322700
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: yajl-ruby
|
82
|
-
requirement: &
|
82
|
+
requirement: &70241536322000 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ~>
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: '1.0'
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70241536322000
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: shoulda
|
93
|
-
requirement: &
|
93
|
+
requirement: &70241536321420 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ! '>='
|
@@ -98,10 +98,10 @@ dependencies:
|
|
98
98
|
version: '0'
|
99
99
|
type: :development
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *70241536321420
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
103
|
name: mocha
|
104
|
-
requirement: &
|
104
|
+
requirement: &70241536320760 !ruby/object:Gem::Requirement
|
105
105
|
none: false
|
106
106
|
requirements:
|
107
107
|
- - ! '>='
|
@@ -109,10 +109,21 @@ dependencies:
|
|
109
109
|
version: '0'
|
110
110
|
type: :development
|
111
111
|
prerelease: false
|
112
|
-
version_requirements: *
|
112
|
+
version_requirements: *70241536320760
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: minitest
|
115
|
+
requirement: &70241536320180 !ruby/object:Gem::Requirement
|
116
|
+
none: false
|
117
|
+
requirements:
|
118
|
+
- - ~>
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '2.12'
|
121
|
+
type: :development
|
122
|
+
prerelease: false
|
123
|
+
version_requirements: *70241536320180
|
113
124
|
- !ruby/object:Gem::Dependency
|
114
125
|
name: activerecord
|
115
|
-
requirement: &
|
126
|
+
requirement: &70241536319540 !ruby/object:Gem::Requirement
|
116
127
|
none: false
|
117
128
|
requirements:
|
118
129
|
- - ! '>='
|
@@ -120,10 +131,10 @@ dependencies:
|
|
120
131
|
version: '3.0'
|
121
132
|
type: :development
|
122
133
|
prerelease: false
|
123
|
-
version_requirements: *
|
134
|
+
version_requirements: *70241536319540
|
124
135
|
- !ruby/object:Gem::Dependency
|
125
136
|
name: sqlite3
|
126
|
-
requirement: &
|
137
|
+
requirement: &70241536319060 !ruby/object:Gem::Requirement
|
127
138
|
none: false
|
128
139
|
requirements:
|
129
140
|
- - ! '>='
|
@@ -131,10 +142,10 @@ dependencies:
|
|
131
142
|
version: '0'
|
132
143
|
type: :development
|
133
144
|
prerelease: false
|
134
|
-
version_requirements: *
|
145
|
+
version_requirements: *70241536319060
|
135
146
|
- !ruby/object:Gem::Dependency
|
136
147
|
name: mongoid
|
137
|
-
requirement: &
|
148
|
+
requirement: &70241536318220 !ruby/object:Gem::Requirement
|
138
149
|
none: false
|
139
150
|
requirements:
|
140
151
|
- - ~>
|
@@ -142,10 +153,10 @@ dependencies:
|
|
142
153
|
version: '2.2'
|
143
154
|
type: :development
|
144
155
|
prerelease: false
|
145
|
-
version_requirements: *
|
156
|
+
version_requirements: *70241536318220
|
146
157
|
- !ruby/object:Gem::Dependency
|
147
158
|
name: bson_ext
|
148
|
-
requirement: &
|
159
|
+
requirement: &70241536317400 !ruby/object:Gem::Requirement
|
149
160
|
none: false
|
150
161
|
requirements:
|
151
162
|
- - ! '>='
|
@@ -153,10 +164,10 @@ dependencies:
|
|
153
164
|
version: '0'
|
154
165
|
type: :development
|
155
166
|
prerelease: false
|
156
|
-
version_requirements: *
|
167
|
+
version_requirements: *70241536317400
|
157
168
|
- !ruby/object:Gem::Dependency
|
158
169
|
name: redis-persistence
|
159
|
-
requirement: &
|
170
|
+
requirement: &70241536316820 !ruby/object:Gem::Requirement
|
160
171
|
none: false
|
161
172
|
requirements:
|
162
173
|
- - ! '>='
|
@@ -164,10 +175,10 @@ dependencies:
|
|
164
175
|
version: '0'
|
165
176
|
type: :development
|
166
177
|
prerelease: false
|
167
|
-
version_requirements: *
|
178
|
+
version_requirements: *70241536316820
|
168
179
|
- !ruby/object:Gem::Dependency
|
169
180
|
name: curb
|
170
|
-
requirement: &
|
181
|
+
requirement: &70241536316100 !ruby/object:Gem::Requirement
|
171
182
|
none: false
|
172
183
|
requirements:
|
173
184
|
- - ! '>='
|
@@ -175,10 +186,10 @@ dependencies:
|
|
175
186
|
version: '0'
|
176
187
|
type: :development
|
177
188
|
prerelease: false
|
178
|
-
version_requirements: *
|
189
|
+
version_requirements: *70241536316100
|
179
190
|
- !ruby/object:Gem::Dependency
|
180
|
-
name:
|
181
|
-
requirement: &
|
191
|
+
name: oj
|
192
|
+
requirement: &70241536339520 !ruby/object:Gem::Requirement
|
182
193
|
none: false
|
183
194
|
requirements:
|
184
195
|
- - ! '>='
|
@@ -186,10 +197,10 @@ dependencies:
|
|
186
197
|
version: '0'
|
187
198
|
type: :development
|
188
199
|
prerelease: false
|
189
|
-
version_requirements: *
|
200
|
+
version_requirements: *70241536339520
|
190
201
|
- !ruby/object:Gem::Dependency
|
191
202
|
name: turn
|
192
|
-
requirement: &
|
203
|
+
requirement: &70241536336900 !ruby/object:Gem::Requirement
|
193
204
|
none: false
|
194
205
|
requirements:
|
195
206
|
- - ~>
|
@@ -197,18 +208,7 @@ dependencies:
|
|
197
208
|
version: '0.9'
|
198
209
|
type: :development
|
199
210
|
prerelease: false
|
200
|
-
version_requirements: *
|
201
|
-
- !ruby/object:Gem::Dependency
|
202
|
-
name: rdoc
|
203
|
-
requirement: &70223215704680 !ruby/object:Gem::Requirement
|
204
|
-
none: false
|
205
|
-
requirements:
|
206
|
-
- - ! '>='
|
207
|
-
- !ruby/object:Gem::Version
|
208
|
-
version: '0'
|
209
|
-
type: :development
|
210
|
-
prerelease: false
|
211
|
-
version_requirements: *70223215704680
|
211
|
+
version_requirements: *70241536336900
|
212
212
|
description: ! " Tire is a Ruby client for the ElasticSearch search engine/database.\n\n
|
213
213
|
\ It provides Ruby-like API for fluent communication with the ElasticSearch server\n
|
214
214
|
\ and blends with ActiveModel class for convenient usage in Rails applications.\n\n
|
@@ -283,6 +283,7 @@ files:
|
|
283
283
|
- test/integration/active_record_searchable_test.rb
|
284
284
|
- test/integration/boolean_queries_test.rb
|
285
285
|
- test/integration/boosting_queries_test.rb
|
286
|
+
- test/integration/bulk_test.rb
|
286
287
|
- test/integration/count_test.rb
|
287
288
|
- test/integration/custom_score_queries_test.rb
|
288
289
|
- test/integration/dis_max_queries_test.rb
|
@@ -377,8 +378,10 @@ post_install_message: ! "=======================================================
|
|
377
378
|
to Index#retrieve\n * Allow building the search request step-by-step in Tire's
|
378
379
|
DSL [#496]\n * Added a `match` query type\n * Added support for multisearch (_msearch)
|
379
380
|
and the `Tire.multi_search` DSL method\n * Added support for multi-search in the
|
380
|
-
ActiveModel integration and in Tire::Model::Persistence\n
|
381
|
-
|
381
|
+
ActiveModel integration and in Tire::Model::Persistence\n * Added support for create
|
382
|
+
and delete actions for Index#bulk\n * Added support for meta information (`_routing`,
|
383
|
+
`_parent`, etc) in Index#bulk\n * Added support for URL parameters (`refresh`,
|
384
|
+
`consistency`) in Index#bulk\n\n See the full changelog at <http://github.com/karmi/tire/commits/v0.5.1>.\n\n--------------------------------------------------------------------------------\n"
|
382
385
|
rdoc_options:
|
383
386
|
- --charset=UTF-8
|
384
387
|
require_paths:
|
@@ -412,6 +415,7 @@ test_files:
|
|
412
415
|
- test/integration/active_record_searchable_test.rb
|
413
416
|
- test/integration/boolean_queries_test.rb
|
414
417
|
- test/integration/boosting_queries_test.rb
|
418
|
+
- test/integration/bulk_test.rb
|
415
419
|
- test/integration/count_test.rb
|
416
420
|
- test/integration/custom_score_queries_test.rb
|
417
421
|
- test/integration/dis_max_queries_test.rb
|