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,113 @@
|
|
1
|
+
require File.expand_path('../../test_helper', __FILE__)
|
2
|
+
|
3
|
+
describe Elastomer::Client::Cluster do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@name = 'elastomer-cluster-test'
|
7
|
+
@index = $client.index @name
|
8
|
+
@index.delete if @index.exists?
|
9
|
+
@cluster = $client.cluster
|
10
|
+
end
|
11
|
+
|
12
|
+
after do
|
13
|
+
@index.delete if @index.exists?
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'gets the cluster health' do
|
17
|
+
h = @cluster.health
|
18
|
+
assert h.key?('cluster_name'), 'the cluster name is returned'
|
19
|
+
assert h.key?('status'), 'the cluster status is returned'
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'gets the cluster state' do
|
23
|
+
h = @cluster.state
|
24
|
+
assert h.key?('cluster_name'), 'the cluster name is returned'
|
25
|
+
assert h.key?('master_node'), 'the master node is returned'
|
26
|
+
assert_instance_of Hash, h['nodes'], 'the node list is returned'
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'gets the cluster settings' do
|
30
|
+
h = @cluster.settings
|
31
|
+
assert_instance_of Hash, h['persistent'], 'the persistent settings are returned'
|
32
|
+
assert_instance_of Hash, h['transient'], 'the transient settings are returned'
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'updates the cluster settings' do
|
36
|
+
@cluster.update_settings :transient => { 'indices.ttl.interval' => "30" }
|
37
|
+
h = @cluster.settings
|
38
|
+
|
39
|
+
#COMPATIBILITY
|
40
|
+
# ES 1.0 changed the default return format of cluster settings to always
|
41
|
+
# expand nested properties, e.g.
|
42
|
+
# {"indices.ttl.interval": "30"} changed to
|
43
|
+
# {"indices": {"ttl": {"interval":"30"}}}
|
44
|
+
|
45
|
+
# To support both versions, we check for either return format.
|
46
|
+
value = h['transient']['indices.ttl.interval'] ||
|
47
|
+
h['transient']['indices']['ttl']['interval']
|
48
|
+
assert_equal "30", value
|
49
|
+
|
50
|
+
@cluster.update_settings :transient => { 'indices.ttl.interval' => "60" }
|
51
|
+
h = @cluster.settings
|
52
|
+
|
53
|
+
value = h['transient']['indices.ttl.interval'] ||
|
54
|
+
h['transient']['indices']['ttl']['interval']
|
55
|
+
assert_equal "60", value
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'returns the list of nodes in the cluster' do
|
59
|
+
nodes = @cluster.nodes
|
60
|
+
assert !nodes.empty?, 'we have to have some nodes'
|
61
|
+
end
|
62
|
+
|
63
|
+
describe 'when working with aliases' do
|
64
|
+
before do
|
65
|
+
@name = 'elastomer-cluster-test'
|
66
|
+
@index = $client.index @name
|
67
|
+
@index.create({}) unless @index.exists?
|
68
|
+
wait_for_index(@name)
|
69
|
+
end
|
70
|
+
|
71
|
+
after do
|
72
|
+
@index.delete if @index.exists?
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'adds an alias' do
|
76
|
+
hash = @cluster.get_aliases
|
77
|
+
assert_empty hash[@name]['aliases']
|
78
|
+
|
79
|
+
@cluster.update_aliases \
|
80
|
+
:add => {:index => @name, :alias => 'elastomer-test-unikitty'}
|
81
|
+
|
82
|
+
hash = @cluster.get_aliases
|
83
|
+
assert_equal ['elastomer-test-unikitty'], hash[@name]['aliases'].keys
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'removes an alias' do
|
87
|
+
@cluster.update_aliases \
|
88
|
+
:add => {:index => @name, :alias => 'elastomer-test-unikitty'}
|
89
|
+
|
90
|
+
hash = @cluster.get_aliases
|
91
|
+
assert_equal ['elastomer-test-unikitty'], hash[@name]['aliases'].keys
|
92
|
+
|
93
|
+
@cluster.update_aliases([
|
94
|
+
{:add => {:index => @name, :alias => 'elastomer-test-SpongeBob-SquarePants'}},
|
95
|
+
{:remove => {:index => @name, :alias => 'elastomer-test-unikitty'}}
|
96
|
+
])
|
97
|
+
|
98
|
+
hash = @cluster.get_aliases
|
99
|
+
assert_equal ['elastomer-test-SpongeBob-SquarePants'], hash[@name]['aliases'].keys
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'accepts the full aliases actions hash' do
|
103
|
+
@cluster.update_aliases :actions => [
|
104
|
+
{:add => {:index => @name, :alias => 'elastomer-test-He-Man'}},
|
105
|
+
{:add => {:index => @name, :alias => 'elastomer-test-Skeletor'}}
|
106
|
+
]
|
107
|
+
|
108
|
+
hash = @cluster.get_aliases(:index => @name)
|
109
|
+
assert_equal %w[elastomer-test-He-Man elastomer-test-Skeletor], hash[@name]['aliases'].keys.sort
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
@@ -0,0 +1,394 @@
|
|
1
|
+
require File.expand_path('../../test_helper', __FILE__)
|
2
|
+
|
3
|
+
describe Elastomer::Client::Docs do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@name = 'elastomer-docs-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 'autogenerates IDs for documents' do
|
40
|
+
h = @docs.index \
|
41
|
+
:_type => 'doc2',
|
42
|
+
:title => 'the author of logging',
|
43
|
+
:author => 'pea53'
|
44
|
+
|
45
|
+
assert_created h
|
46
|
+
assert_match %r/^\S{22}$/, h['_id']
|
47
|
+
|
48
|
+
h = @docs.index \
|
49
|
+
:_id => nil,
|
50
|
+
:_type => 'doc3',
|
51
|
+
:title => 'the author of rubber-band',
|
52
|
+
:author => 'grantr'
|
53
|
+
|
54
|
+
assert_created h
|
55
|
+
assert_match %r/^\S{22}$/, h['_id']
|
56
|
+
|
57
|
+
h = @docs.index \
|
58
|
+
:_id => '',
|
59
|
+
:_type => 'doc4',
|
60
|
+
:title => 'the author of toml',
|
61
|
+
:author => 'mojombo'
|
62
|
+
|
63
|
+
assert_created h
|
64
|
+
assert_match %r/^\S{22}$/, h['_id']
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'uses the provided document ID' do
|
68
|
+
h = @docs.index \
|
69
|
+
:_id => '42',
|
70
|
+
:_type => 'doc2',
|
71
|
+
:title => 'the author of logging',
|
72
|
+
:author => 'pea53'
|
73
|
+
|
74
|
+
assert_created h
|
75
|
+
assert_equal '42', h['_id']
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'accepts JSON encoded document strings' do
|
79
|
+
h = @docs.index \
|
80
|
+
'{"author":"pea53", "title":"the author of logging"}',
|
81
|
+
:id => '42',
|
82
|
+
:type => 'doc2'
|
83
|
+
|
84
|
+
assert_created h
|
85
|
+
assert_equal '42', h['_id']
|
86
|
+
|
87
|
+
h = @docs.index \
|
88
|
+
'{"author":"grantr", "title":"the author of rubber-band"}',
|
89
|
+
:type => 'doc2'
|
90
|
+
|
91
|
+
assert_created h
|
92
|
+
assert_match %r/^\S{22}$/, h['_id']
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'gets documents from the search index' do
|
96
|
+
h = @docs.get :id => '1', :type => 'doc1'
|
97
|
+
refute_found h
|
98
|
+
|
99
|
+
populate!
|
100
|
+
|
101
|
+
h = @docs.get :id => '1', :type => 'doc1'
|
102
|
+
assert_found h
|
103
|
+
assert_equal 'mojombo', h['_source']['author']
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'gets multiple documents from the search index' do
|
107
|
+
populate!
|
108
|
+
|
109
|
+
h = @docs.multi_get :docs => [
|
110
|
+
{ :_id => 1, :_type => 'doc1' },
|
111
|
+
{ :_id => 1, :_type => 'doc2' }
|
112
|
+
]
|
113
|
+
authors = h['docs'].map { |d| d['_source']['author'] }
|
114
|
+
assert_equal %w[mojombo pea53], authors
|
115
|
+
|
116
|
+
h = @docs.multi_get :ids => [2, 1], :_type => 'doc1'
|
117
|
+
authors = h['docs'].map { |d| d['_source']['author'] }
|
118
|
+
assert_equal %w[defunkt mojombo], authors
|
119
|
+
|
120
|
+
h = @index.docs('doc1').multi_get :ids => [1, 2, 3, 4]
|
121
|
+
assert_found h['docs'][0]
|
122
|
+
assert_found h['docs'][1]
|
123
|
+
refute_found h['docs'][2]
|
124
|
+
refute_found h['docs'][3]
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'deletes documents from the search index' do
|
128
|
+
populate!
|
129
|
+
@docs = @index.docs('doc2')
|
130
|
+
|
131
|
+
h = @docs.multi_get :ids => [1, 2]
|
132
|
+
authors = h['docs'].map { |d| d['_source']['author'] }
|
133
|
+
assert_equal %w[pea53 grantr], authors
|
134
|
+
|
135
|
+
h = @docs.delete :id => 1
|
136
|
+
assert h['found'], "expected document to be found"
|
137
|
+
h = @docs.multi_get :ids => [1, 2]
|
138
|
+
refute_found h['docs'][0]
|
139
|
+
assert_found h['docs'][1]
|
140
|
+
|
141
|
+
assert_raises(ArgumentError) { @docs.delete :id => nil }
|
142
|
+
assert_raises(ArgumentError) { @docs.delete :id => '' }
|
143
|
+
assert_raises(ArgumentError) { @docs.delete :id => "\t" }
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'does not care if you delete a document that is not there' do
|
147
|
+
@docs = @index.docs('doc2')
|
148
|
+
h = @docs.delete :id => 42
|
149
|
+
|
150
|
+
refute h['found'], 'expected document to not be found'
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'deletes documents by query' do
|
154
|
+
populate!
|
155
|
+
@docs = @index.docs('doc2')
|
156
|
+
|
157
|
+
h = @docs.multi_get :ids => [1, 2]
|
158
|
+
authors = h['docs'].map { |d| d['_source']['author'] }
|
159
|
+
assert_equal %w[pea53 grantr], authors
|
160
|
+
|
161
|
+
h = @docs.delete_by_query(:q => "author:grantr")
|
162
|
+
@index.refresh
|
163
|
+
h = @docs.multi_get :ids => [1, 2]
|
164
|
+
assert_found h['docs'][0]
|
165
|
+
refute_found h['docs'][1]
|
166
|
+
|
167
|
+
#COMPATIBILITY
|
168
|
+
# ES 1.0 normalized all search APIs to use a :query top level element.
|
169
|
+
# This broke compatibility with the ES 0.90 delete_by_query api. Since
|
170
|
+
# the query hash version of this api never worked with 0.90 in the first
|
171
|
+
# place, only test it if running 1.0.
|
172
|
+
if es_version_1_x?
|
173
|
+
h = @docs.delete_by_query(
|
174
|
+
:query => {
|
175
|
+
:filtered => {
|
176
|
+
:query => {:match_all => {}},
|
177
|
+
:filter => {:term => {:author => 'pea53'}}
|
178
|
+
}
|
179
|
+
}
|
180
|
+
)
|
181
|
+
@index.refresh
|
182
|
+
h = @docs.multi_get :ids => [1, 2]
|
183
|
+
refute_found h['docs'][0]
|
184
|
+
refute_found h['docs'][1]
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'searches for documents' do
|
189
|
+
h = @docs.search :q => '*:*'
|
190
|
+
assert_equal 0, h['hits']['total']
|
191
|
+
|
192
|
+
populate!
|
193
|
+
|
194
|
+
h = @docs.search :q => '*:*'
|
195
|
+
assert_equal 4, h['hits']['total']
|
196
|
+
|
197
|
+
h = @docs.search :q => '*:*', :type => 'doc1'
|
198
|
+
assert_equal 2, h['hits']['total']
|
199
|
+
|
200
|
+
h = @docs.search({
|
201
|
+
:query => {:match_all => {}},
|
202
|
+
:filter => {:term => {:author => 'defunkt'}}
|
203
|
+
}, :type => %w[doc1 doc2] )
|
204
|
+
assert_equal 1, h['hits']['total']
|
205
|
+
|
206
|
+
hit = h['hits']['hits'].first
|
207
|
+
assert_equal 'the author of resque', hit['_source']['title']
|
208
|
+
end
|
209
|
+
|
210
|
+
it 'counts documents' do
|
211
|
+
h = @docs.count :q => '*:*'
|
212
|
+
assert_equal 0, h['count']
|
213
|
+
|
214
|
+
populate!
|
215
|
+
|
216
|
+
h = @docs.count :q => '*:*'
|
217
|
+
assert_equal 4, h['count']
|
218
|
+
|
219
|
+
h = @docs.count :q => '*:*', :type => 'doc1'
|
220
|
+
assert_equal 2, h['count']
|
221
|
+
|
222
|
+
h = @docs.count :q => '*:*', :type => 'doc1,doc2'
|
223
|
+
assert_equal 4, h['count']
|
224
|
+
|
225
|
+
#COMPATIBILITY
|
226
|
+
# ES 1.0 normalized all search APIs to use a :query top level element.
|
227
|
+
# This broke compatibility with the ES 0.90 count api.
|
228
|
+
if es_version_1_x?
|
229
|
+
h = @docs.count({
|
230
|
+
:query => {
|
231
|
+
:filtered => {
|
232
|
+
:query => {:match_all => {}},
|
233
|
+
:filter => {:term => {:author => 'defunkt'}}
|
234
|
+
}
|
235
|
+
}
|
236
|
+
}, :type => %w[doc1 doc2] )
|
237
|
+
else
|
238
|
+
h = @docs.count({
|
239
|
+
:filtered => {
|
240
|
+
:query => {:match_all => {}},
|
241
|
+
:filter => {:term => {:author => 'defunkt'}}
|
242
|
+
}
|
243
|
+
}, :type => %w[doc1 doc2] )
|
244
|
+
end
|
245
|
+
assert_equal 1, h['count']
|
246
|
+
end
|
247
|
+
|
248
|
+
it 'searches for more like this' do
|
249
|
+
populate!
|
250
|
+
|
251
|
+
# for some reason, if there's no document indexed here all the mlt
|
252
|
+
# queries return zero results
|
253
|
+
@docs.add \
|
254
|
+
:_id => 3,
|
255
|
+
:_type => 'doc1',
|
256
|
+
:title => 'the author of faraday',
|
257
|
+
:author => 'technoweenie'
|
258
|
+
|
259
|
+
@index.refresh
|
260
|
+
|
261
|
+
h = @docs.more_like_this({
|
262
|
+
:type => 'doc1',
|
263
|
+
:id => 1,
|
264
|
+
:mlt_fields => 'title',
|
265
|
+
:min_term_freq => 1
|
266
|
+
})
|
267
|
+
assert_equal 2, h["hits"]["total"]
|
268
|
+
|
269
|
+
h = @docs.more_like_this({
|
270
|
+
:facets => {
|
271
|
+
"author" => {
|
272
|
+
:terms => {
|
273
|
+
:field => "author"
|
274
|
+
}
|
275
|
+
}
|
276
|
+
}
|
277
|
+
}, {
|
278
|
+
:type => 'doc1',
|
279
|
+
:id => 1,
|
280
|
+
:mlt_fields => 'title,author',
|
281
|
+
:min_term_freq => 1
|
282
|
+
})
|
283
|
+
assert_equal 2, h["hits"]["total"]
|
284
|
+
assert_equal 2, h["facets"]["author"]["total"]
|
285
|
+
end
|
286
|
+
|
287
|
+
it 'explains scoring' do
|
288
|
+
populate!
|
289
|
+
|
290
|
+
h = @docs.explain({
|
291
|
+
:query => {
|
292
|
+
:match => {
|
293
|
+
"author" => "defunkt"
|
294
|
+
}
|
295
|
+
}
|
296
|
+
}, :type => 'doc1', :id => 2)
|
297
|
+
assert_equal true, h["matched"]
|
298
|
+
|
299
|
+
h = @docs.explain(:type => 'doc2', :id => 2, :q => "pea53")
|
300
|
+
assert_equal false, h["matched"]
|
301
|
+
end
|
302
|
+
|
303
|
+
it 'validates queries' do
|
304
|
+
populate!
|
305
|
+
|
306
|
+
h = @docs.validate :q => '*:*'
|
307
|
+
assert_equal true, h["valid"]
|
308
|
+
|
309
|
+
#COMPATIBILITY
|
310
|
+
# ES 1.0 normalized all search APIs to use a :query top level element.
|
311
|
+
# This broke compatibility with the ES 0.90 validate api.
|
312
|
+
if es_version_1_x?
|
313
|
+
h = @docs.validate({
|
314
|
+
:query => {
|
315
|
+
:filtered => {
|
316
|
+
:query => {:match_all => {}},
|
317
|
+
:filter => {:term => {:author => 'defunkt'}}
|
318
|
+
}
|
319
|
+
}
|
320
|
+
}, :type => %w[doc1 doc2] )
|
321
|
+
else
|
322
|
+
h = @docs.validate({
|
323
|
+
:filtered => {
|
324
|
+
:query => {:match_all => {}},
|
325
|
+
:filter => {:term => {:author => 'defunkt'}}
|
326
|
+
}
|
327
|
+
}, :type => %w[doc1 doc2] )
|
328
|
+
end
|
329
|
+
assert_equal true, h["valid"]
|
330
|
+
end
|
331
|
+
|
332
|
+
it 'updates documents' do
|
333
|
+
populate!
|
334
|
+
|
335
|
+
h = @docs.get :id => '1', :type => 'doc1'
|
336
|
+
assert_found h
|
337
|
+
assert_equal 'mojombo', h['_source']['author']
|
338
|
+
|
339
|
+
@docs.update({
|
340
|
+
:_id => '1',
|
341
|
+
:_type => 'doc1',
|
342
|
+
:doc => {:author => 'TwP'}
|
343
|
+
})
|
344
|
+
h = @docs.get :id => '1', :type => 'doc1'
|
345
|
+
assert_found h
|
346
|
+
assert_equal 'TwP', h['_source']['author']
|
347
|
+
|
348
|
+
if $client.version >= "0.90"
|
349
|
+
@docs.update({
|
350
|
+
:_id => '42',
|
351
|
+
:_type => 'doc1',
|
352
|
+
:doc => {
|
353
|
+
:author => 'TwP',
|
354
|
+
:title => 'the ineffable beauty of search'
|
355
|
+
},
|
356
|
+
:doc_as_upsert => true
|
357
|
+
})
|
358
|
+
|
359
|
+
h = @docs.get :id => '42', :type => 'doc1'
|
360
|
+
assert_found h
|
361
|
+
assert_equal 'TwP', h['_source']['author']
|
362
|
+
assert_equal 'the ineffable beauty of search', h['_source']['title']
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
def populate!
|
367
|
+
@docs.add \
|
368
|
+
:_id => 1,
|
369
|
+
:_type => 'doc1',
|
370
|
+
:title => 'the author of gravatar',
|
371
|
+
:author => 'mojombo'
|
372
|
+
|
373
|
+
@docs.add \
|
374
|
+
:_id => 2,
|
375
|
+
:_type => 'doc1',
|
376
|
+
:title => 'the author of resque',
|
377
|
+
:author => 'defunkt'
|
378
|
+
|
379
|
+
@docs.add \
|
380
|
+
:_id => 1,
|
381
|
+
:_type => 'doc2',
|
382
|
+
:title => 'the author of logging',
|
383
|
+
:author => 'pea53'
|
384
|
+
|
385
|
+
@docs.add \
|
386
|
+
:_id => 2,
|
387
|
+
:_type => 'doc2',
|
388
|
+
:title => 'the author of rubber-band',
|
389
|
+
:author => 'grantr'
|
390
|
+
|
391
|
+
@index.refresh
|
392
|
+
end
|
393
|
+
|
394
|
+
end
|