tire 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|