elastomer-client 0.3.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.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +4 -0
- data/Gemfile +5 -0
- data/LICENSE.txt +22 -0
- data/README.md +108 -0
- data/Rakefile +9 -0
- data/docs/notifications.md +71 -0
- data/elastomer-client.gemspec +30 -0
- data/lib/elastomer/client.rb +307 -0
- data/lib/elastomer/client/bulk.rb +257 -0
- data/lib/elastomer/client/cluster.rb +208 -0
- data/lib/elastomer/client/docs.rb +432 -0
- data/lib/elastomer/client/errors.rb +51 -0
- data/lib/elastomer/client/index.rb +407 -0
- data/lib/elastomer/client/multi_search.rb +115 -0
- data/lib/elastomer/client/nodes.rb +87 -0
- data/lib/elastomer/client/scan.rb +161 -0
- data/lib/elastomer/client/template.rb +85 -0
- data/lib/elastomer/client/warmer.rb +96 -0
- data/lib/elastomer/core_ext/time.rb +7 -0
- data/lib/elastomer/middleware/encode_json.rb +51 -0
- data/lib/elastomer/middleware/opaque_id.rb +69 -0
- data/lib/elastomer/middleware/parse_json.rb +39 -0
- data/lib/elastomer/notifications.rb +83 -0
- data/lib/elastomer/version.rb +7 -0
- data/script/bootstrap +16 -0
- data/script/cibuild +28 -0
- data/script/console +9 -0
- data/script/testsuite +10 -0
- data/test/assertions.rb +74 -0
- data/test/client/bulk_test.rb +226 -0
- data/test/client/cluster_test.rb +113 -0
- data/test/client/docs_test.rb +394 -0
- data/test/client/index_test.rb +244 -0
- data/test/client/multi_search_test.rb +129 -0
- data/test/client/nodes_test.rb +35 -0
- data/test/client/scan_test.rb +84 -0
- data/test/client/stubbed_client_tests.rb +40 -0
- data/test/client/template_test.rb +33 -0
- data/test/client/warmer_test.rb +56 -0
- data/test/client_test.rb +86 -0
- data/test/core_ext/time_test.rb +46 -0
- data/test/middleware/encode_json_test.rb +53 -0
- data/test/middleware/opaque_id_test.rb +39 -0
- data/test/middleware/parse_json_test.rb +54 -0
- data/test/test_helper.rb +94 -0
- metadata +210 -0
@@ -0,0 +1,244 @@
|
|
1
|
+
require File.expand_path('../../test_helper', __FILE__)
|
2
|
+
|
3
|
+
describe Elastomer::Client::Index do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@name = 'elastomer-index-test'
|
7
|
+
@index = $client.index @name
|
8
|
+
@index.delete if @index.exists?
|
9
|
+
end
|
10
|
+
|
11
|
+
after do
|
12
|
+
@index.delete if @index.exists?
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'requires an index name' do
|
16
|
+
assert_raises(ArgumentError) { $client.index }
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'determines if an index exists' do
|
20
|
+
assert !@index.exists?, 'the index should not yet exist'
|
21
|
+
end
|
22
|
+
|
23
|
+
describe 'when creating an index' do
|
24
|
+
it 'creates an index' do
|
25
|
+
@index.create :settings => { :number_of_shards => 3, :number_of_replicas => 0 }
|
26
|
+
assert @index.exists?, 'the index should now exist'
|
27
|
+
|
28
|
+
settings = @index.settings[@name]['settings']
|
29
|
+
|
30
|
+
# COMPATIBILITY
|
31
|
+
# ES 1.0 changed the default return format of index settings to always
|
32
|
+
# expand nested properties, e.g.
|
33
|
+
# {"index.number_of_replicas": "1"} changed to
|
34
|
+
# {"index": {"number_of_replicas":"1"}}
|
35
|
+
|
36
|
+
# To support both versions, we check for either return format.
|
37
|
+
value = settings['index.number_of_shards'] ||
|
38
|
+
settings['index']['number_of_shards']
|
39
|
+
assert_equal '3', value
|
40
|
+
value = settings['index.number_of_replicas'] ||
|
41
|
+
settings['index']['number_of_replicas']
|
42
|
+
assert_equal '0', value
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'adds mappings for document types' do
|
46
|
+
@index.create(
|
47
|
+
:settings => { :number_of_shards => 1, :number_of_replicas => 0 },
|
48
|
+
:mappings => {
|
49
|
+
:doco => {
|
50
|
+
:_source => { :enabled => false },
|
51
|
+
:_all => { :enabled => false },
|
52
|
+
:properties => {
|
53
|
+
:title => { :type => 'string', :analyzer => 'standard' },
|
54
|
+
:author => { :type => 'string', :index => 'not_analyzed' }
|
55
|
+
}
|
56
|
+
}
|
57
|
+
}
|
58
|
+
)
|
59
|
+
|
60
|
+
assert @index.exists?, 'the index should now exist'
|
61
|
+
assert_mapping_exists @index.mapping[@name], 'doco'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'updates index settings' do
|
66
|
+
@index.create :settings => { :number_of_shards => 1, :number_of_replicas => 0 }
|
67
|
+
|
68
|
+
@index.update_settings 'index.number_of_replicas' => 1
|
69
|
+
settings = @index.settings[@name]['settings']
|
70
|
+
|
71
|
+
# COMPATIBILITY
|
72
|
+
# ES 1.0 changed the default return format of index settings to always
|
73
|
+
# expand nested properties, e.g.
|
74
|
+
# {"index.number_of_replicas": "1"} changed to
|
75
|
+
# {"index": {"number_of_replicas":"1"}}
|
76
|
+
|
77
|
+
# To support both versions, we check for either return format.
|
78
|
+
value = settings['index.number_of_replicas'] ||
|
79
|
+
settings['index']['number_of_replicas']
|
80
|
+
assert_equal '1', value
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'updates document mappings' do
|
84
|
+
@index.create(
|
85
|
+
:mappings => {
|
86
|
+
:doco => {
|
87
|
+
:_source => { :enabled => false },
|
88
|
+
:_all => { :enabled => false },
|
89
|
+
:properties => {:title => { :type => 'string', :analyzer => 'standard' }}
|
90
|
+
}
|
91
|
+
}
|
92
|
+
)
|
93
|
+
|
94
|
+
assert_property_exists @index.mapping[@name], 'doco', 'title'
|
95
|
+
|
96
|
+
@index.update_mapping 'doco', { :doco => { :properties => {
|
97
|
+
:author => { :type => 'string', :index => 'not_analyzed' }
|
98
|
+
}}}
|
99
|
+
|
100
|
+
assert_property_exists @index.mapping[@name], 'doco', 'author'
|
101
|
+
assert_property_exists @index.mapping[@name], 'doco', 'title'
|
102
|
+
|
103
|
+
@index.update_mapping 'mux_mool', { :mux_mool => { :properties => {
|
104
|
+
:song => { :type => 'string', :index => 'not_analyzed' }
|
105
|
+
}}}
|
106
|
+
|
107
|
+
assert_property_exists @index.mapping[@name], 'mux_mool', 'song'
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'deletes document mappings' do
|
111
|
+
@index.create(
|
112
|
+
:mappings => {
|
113
|
+
:doco => {
|
114
|
+
:_source => { :enabled => false },
|
115
|
+
:_all => { :enabled => false },
|
116
|
+
:properties => {:title => { :type => 'string', :analyzer => 'standard' }}
|
117
|
+
}
|
118
|
+
}
|
119
|
+
)
|
120
|
+
assert_mapping_exists @index.mapping[@name], 'doco'
|
121
|
+
|
122
|
+
response = @index.delete_mapping 'doco'
|
123
|
+
assert_acknowledged response
|
124
|
+
assert @index.mapping == {} || @index.mapping[@name] == {}
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'lists all aliases to the index' do
|
128
|
+
@index.create(nil)
|
129
|
+
assert_equal({@name => {'aliases' => {}}}, @index.get_aliases)
|
130
|
+
|
131
|
+
$client.cluster.update_aliases :add => {:index => @name, :alias => 'foofaloo'}
|
132
|
+
assert_equal({@name => {'aliases' => {'foofaloo' => {}}}}, @index.get_aliases)
|
133
|
+
end
|
134
|
+
|
135
|
+
# COMPATIBILITY ES 1.x removed English stopwords from the default analyzers,
|
136
|
+
# so create a custom one with the English stopwords added.
|
137
|
+
if es_version_1_x?
|
138
|
+
it 'analyzes text and returns tokens' do
|
139
|
+
tokens = @index.analyze 'Just a few words to analyze.', :analyzer => 'standard', :index => nil
|
140
|
+
tokens = tokens['tokens'].map { |h| h['token'] }
|
141
|
+
assert_equal %w[just a few words to analyze], tokens
|
142
|
+
|
143
|
+
@index.create(
|
144
|
+
:settings => {
|
145
|
+
:number_of_shards => 1,
|
146
|
+
:number_of_replicas => 0,
|
147
|
+
:analysis => {
|
148
|
+
:analyzer => {
|
149
|
+
:english_standard => {
|
150
|
+
:type => :standard,
|
151
|
+
:stopwords => "_english_"
|
152
|
+
}
|
153
|
+
}
|
154
|
+
}
|
155
|
+
}
|
156
|
+
)
|
157
|
+
|
158
|
+
tokens = @index.analyze 'Just a few words to analyze.', :analyzer => 'english_standard'
|
159
|
+
tokens = tokens['tokens'].map { |h| h['token'] }
|
160
|
+
assert_equal %w[just few words analyze], tokens
|
161
|
+
end
|
162
|
+
else
|
163
|
+
it 'analyzes text and returns tokens' do
|
164
|
+
tokens = @index.analyze 'Just a few words to analyze.', :index => nil
|
165
|
+
tokens = tokens['tokens'].map { |h| h['token'] }
|
166
|
+
assert_equal %w[just few words analyze], tokens
|
167
|
+
|
168
|
+
tokens = @index.analyze 'Just a few words to analyze.', :analyzer => 'simple', :index => nil
|
169
|
+
tokens = tokens['tokens'].map { |h| h['token'] }
|
170
|
+
assert_equal %w[just a few words to analyze], tokens
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
describe "when an index exists" do
|
175
|
+
before do
|
176
|
+
@index.create(nil)
|
177
|
+
wait_for_index(@name)
|
178
|
+
end
|
179
|
+
|
180
|
+
#TODO assert this only hits the desired index
|
181
|
+
it 'deletes' do
|
182
|
+
response = @index.delete
|
183
|
+
assert_acknowledged response
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'opens' do
|
187
|
+
response = @index.open
|
188
|
+
assert_acknowledged response
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'closes' do
|
192
|
+
response = @index.close
|
193
|
+
assert_acknowledged response
|
194
|
+
end
|
195
|
+
|
196
|
+
it 'refreshes' do
|
197
|
+
response = @index.refresh
|
198
|
+
assert_equal 0, response["_shards"]["failed"]
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'flushes' do
|
202
|
+
response = @index.flush
|
203
|
+
assert_equal 0, response["_shards"]["failed"]
|
204
|
+
end
|
205
|
+
|
206
|
+
it 'optimizes' do
|
207
|
+
response = @index.optimize
|
208
|
+
assert_equal 0, response["_shards"]["failed"]
|
209
|
+
end
|
210
|
+
|
211
|
+
# COMPATIBILITY ES 1.2 removed support for the gateway snapshot API.
|
212
|
+
if es_version_supports_gateway_snapshots?
|
213
|
+
it 'snapshots' do
|
214
|
+
response = @index.snapshot
|
215
|
+
assert_equal 0, response["_shards"]["failed"]
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
it 'clears caches' do
|
220
|
+
response = @index.clear_cache
|
221
|
+
assert_equal 0, response["_shards"]["failed"]
|
222
|
+
end
|
223
|
+
|
224
|
+
it 'gets stats' do
|
225
|
+
response = @index.stats
|
226
|
+
if response.key? 'indices'
|
227
|
+
assert_includes response["indices"], "elastomer-index-test"
|
228
|
+
else
|
229
|
+
assert_includes response["_all"]["indices"], "elastomer-index-test"
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
it 'gets status' do
|
234
|
+
response = @index.status
|
235
|
+
assert_includes response["indices"], "elastomer-index-test"
|
236
|
+
end
|
237
|
+
|
238
|
+
it 'gets segments' do
|
239
|
+
@index.docs('foo').index("foo" => "bar")
|
240
|
+
response = @index.segments
|
241
|
+
assert_includes response["indices"], "elastomer-index-test"
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require File.expand_path('../../test_helper', __FILE__)
|
2
|
+
|
3
|
+
describe Elastomer::Client::MultiSearch do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@name = 'elastomer-msearch-test'
|
7
|
+
@index = $client.index(@name)
|
8
|
+
|
9
|
+
unless @index.exists?
|
10
|
+
@index.create \
|
11
|
+
:settings => { 'index.number_of_shards' => 1, 'index.number_of_replicas' => 0 },
|
12
|
+
:mappings => {
|
13
|
+
:doc1 => {
|
14
|
+
:_source => { :enabled => true }, :_all => { :enabled => false },
|
15
|
+
:properties => {
|
16
|
+
:title => { :type => 'string', :analyzer => 'standard' },
|
17
|
+
:author => { :type => 'string', :index => 'not_analyzed' }
|
18
|
+
}
|
19
|
+
},
|
20
|
+
:doc2 => {
|
21
|
+
:_source => { :enabled => true }, :_all => { :enabled => false },
|
22
|
+
:properties => {
|
23
|
+
:title => { :type => 'string', :analyzer => 'standard' },
|
24
|
+
:author => { :type => 'string', :index => 'not_analyzed' }
|
25
|
+
}
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
wait_for_index(@name)
|
30
|
+
end
|
31
|
+
|
32
|
+
@docs = @index.docs
|
33
|
+
end
|
34
|
+
|
35
|
+
after do
|
36
|
+
@index.delete if @index.exists?
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'performs multisearches' do
|
40
|
+
populate!
|
41
|
+
|
42
|
+
body = [
|
43
|
+
'{"index" : "elastomer-msearch-test", "search_type" : "count"}',
|
44
|
+
'{"query" : {"match_all" : {}}}',
|
45
|
+
'{"index" : "elastomer-msearch-test", "type": "doc2"}',
|
46
|
+
'{"query" : {"match": {"author" : "grantr"}}}',
|
47
|
+
nil
|
48
|
+
]
|
49
|
+
body = body.join "\n"
|
50
|
+
h = $client.multi_search body
|
51
|
+
response1, response2 = h["responses"]
|
52
|
+
assert_equal 4, response1["hits"]["total"]
|
53
|
+
assert_equal 1, response2["hits"]["total"]
|
54
|
+
assert_equal "2", response2["hits"]["hits"][0]["_id"]
|
55
|
+
|
56
|
+
body = [
|
57
|
+
'{}',
|
58
|
+
'{"query" : {"match": {"author" : "grantr"}}}',
|
59
|
+
nil
|
60
|
+
]
|
61
|
+
body = body.join "\n"
|
62
|
+
h = $client.multi_search body, :index => @name
|
63
|
+
response1 = h["responses"].first
|
64
|
+
assert_equal 1, response1["hits"]["total"]
|
65
|
+
assert_equal "2", response1["hits"]["hits"][0]["_id"]
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'supports a nice block syntax' do
|
69
|
+
populate!
|
70
|
+
|
71
|
+
h = $client.multi_search do |m|
|
72
|
+
m.search({:query => { :match_all => {}}}, :index => @name, :search_type => :count)
|
73
|
+
m.search({:query => { :match => { "title" => "author" }}}, :index => @name, :type => 'doc2')
|
74
|
+
end
|
75
|
+
|
76
|
+
response1, response2 = h["responses"]
|
77
|
+
|
78
|
+
assert_equal 4, response1["hits"]["total"]
|
79
|
+
assert_equal 2, response2["hits"]["total"]
|
80
|
+
|
81
|
+
h = @index.multi_search do |m|
|
82
|
+
m.search({:query => { :match_all => {}}}, :search_type => :count)
|
83
|
+
m.search({:query => { :match => { "title" => "author" }}}, :type => 'doc2')
|
84
|
+
end
|
85
|
+
|
86
|
+
response1, response2 = h["responses"]
|
87
|
+
|
88
|
+
assert_equal 4, response1["hits"]["total"]
|
89
|
+
assert_equal 2, response2["hits"]["total"]
|
90
|
+
|
91
|
+
h = @index.docs('doc1').multi_search do |m|
|
92
|
+
m.search({:query => { :match_all => {}}}, :search_type => :count)
|
93
|
+
m.search({:query => { :match => { "title" => "logging" }}}, :type => 'doc2')
|
94
|
+
end
|
95
|
+
|
96
|
+
response1, response2 = h["responses"]
|
97
|
+
|
98
|
+
assert_equal 2, response1["hits"]["total"]
|
99
|
+
assert_equal 1, response2["hits"]["total"]
|
100
|
+
end
|
101
|
+
|
102
|
+
def populate!
|
103
|
+
@docs.add \
|
104
|
+
:_id => 1,
|
105
|
+
:_type => 'doc1',
|
106
|
+
:title => 'the author of gravatar',
|
107
|
+
:author => 'mojombo'
|
108
|
+
|
109
|
+
@docs.add \
|
110
|
+
:_id => 2,
|
111
|
+
:_type => 'doc1',
|
112
|
+
:title => 'the author of resque',
|
113
|
+
:author => 'defunkt'
|
114
|
+
|
115
|
+
@docs.add \
|
116
|
+
:_id => 1,
|
117
|
+
:_type => 'doc2',
|
118
|
+
:title => 'the author of logging',
|
119
|
+
:author => 'pea53'
|
120
|
+
|
121
|
+
@docs.add \
|
122
|
+
:_id => 2,
|
123
|
+
:_type => 'doc2',
|
124
|
+
:title => 'the author of rubber-band',
|
125
|
+
:author => 'grantr'
|
126
|
+
|
127
|
+
@index.refresh
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.expand_path('../../test_helper', __FILE__)
|
2
|
+
|
3
|
+
describe Elastomer::Client::Nodes do
|
4
|
+
|
5
|
+
it 'gets info for the ndoe(s)' do
|
6
|
+
h = $client.nodes.info
|
7
|
+
assert h.key?('cluster_name'), 'the cluster name is returned'
|
8
|
+
assert_instance_of Hash, h['nodes'], 'the node list is returned'
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'gets stats for the node(s)' do
|
12
|
+
h = $client.nodes.stats
|
13
|
+
assert_instance_of Hash, h['nodes'], 'the node list is returned'
|
14
|
+
|
15
|
+
node = h['nodes'].values.first
|
16
|
+
assert node.key?('indices'), 'indices stats are returned'
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'gets the hot threads for the node(s)' do
|
20
|
+
str = $client.nodes.hot_threads :read_timeout => 2
|
21
|
+
assert_instance_of String, str
|
22
|
+
assert_match %r/cpu usage by thread/, str
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'can be scoped to a single node' do
|
26
|
+
h = $client.nodes('node-with-no-name').info
|
27
|
+
assert_empty h['nodes']
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'can be scoped to a multiple nodes' do
|
31
|
+
h = $client.nodes(%w[node1 node2 node3]).info
|
32
|
+
assert_empty h['nodes']
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require File.expand_path('../../test_helper', __FILE__)
|
2
|
+
|
3
|
+
describe Elastomer::Client::Scan do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@name = 'elastomer-scan-test'
|
7
|
+
@index = $client.index(@name)
|
8
|
+
|
9
|
+
unless @index.exists?
|
10
|
+
@index.create \
|
11
|
+
:settings => { 'index.number_of_shards' => 1, 'index.number_of_replicas' => 0 },
|
12
|
+
:mappings => {
|
13
|
+
:tweet => {
|
14
|
+
:_source => { :enabled => true }, :_all => { :enabled => false },
|
15
|
+
:properties => {
|
16
|
+
:message => { :type => 'string', :analyzer => 'standard' },
|
17
|
+
:author => { :type => 'string', :index => 'not_analyzed' }
|
18
|
+
}
|
19
|
+
},
|
20
|
+
:book => {
|
21
|
+
:_source => { :enabled => true }, :_all => { :enabled => false },
|
22
|
+
:properties => {
|
23
|
+
:title => { :type => 'string', :analyzer => 'standard' },
|
24
|
+
:author => { :type => 'string', :index => 'not_analyzed' }
|
25
|
+
}
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
wait_for_index(@name)
|
30
|
+
populate!
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'scans over all documents in an index' do
|
35
|
+
scan = @index.scan '{"query":{"match_all":{}}}', :size => 10
|
36
|
+
|
37
|
+
counts = {'tweet' => 0, 'book' => 0}
|
38
|
+
scan.each_document { |h| counts[h['_type']] += 1 }
|
39
|
+
|
40
|
+
assert_equal 50, counts['tweet']
|
41
|
+
assert_equal 25, counts['book']
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'restricts the scan to a single document type' do
|
45
|
+
scan = @index.scan '{"query":{"match_all":{}}}', :type => 'book'
|
46
|
+
|
47
|
+
counts = {'tweet' => 0, 'book' => 0}
|
48
|
+
scan.each_document { |h| counts[h['_type']] += 1 }
|
49
|
+
|
50
|
+
assert_equal 0, counts['tweet']
|
51
|
+
assert_equal 25, counts['book']
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'limits results by query' do
|
55
|
+
scan = @index.scan :query => { :bool => { :should => [
|
56
|
+
{:match => {:author => 'pea53'}},
|
57
|
+
{:match => {:title => '17'}}
|
58
|
+
]}}
|
59
|
+
|
60
|
+
counts = {'tweet' => 0, 'book' => 0}
|
61
|
+
scan.each_document { |h| counts[h['_type']] += 1 }
|
62
|
+
|
63
|
+
assert_equal 50, counts['tweet']
|
64
|
+
assert_equal 1, counts['book']
|
65
|
+
end
|
66
|
+
|
67
|
+
def populate!
|
68
|
+
h = @index.bulk do |b|
|
69
|
+
50.times { |num|
|
70
|
+
b.index %Q({"author":"pea53","message":"this is tweet number #{num}"}), :_id => num, :_type => 'tweet'
|
71
|
+
}
|
72
|
+
end
|
73
|
+
h['items'].each {|item| assert_bulk_index(item) }
|
74
|
+
|
75
|
+
h = @index.bulk do |b|
|
76
|
+
25.times { |num|
|
77
|
+
b.index %Q({"author":"Pratchett","title":"DiscWorld Book #{num}"}), :_id => num, :_type => 'book'
|
78
|
+
}
|
79
|
+
end
|
80
|
+
h['items'].each {|item| assert_bulk_index(item) }
|
81
|
+
|
82
|
+
@index.refresh
|
83
|
+
end
|
84
|
+
end
|