elastomer-client 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +12 -0
  4. data/CHANGELOG.md +15 -0
  5. data/README.md +6 -7
  6. data/Rakefile +21 -0
  7. data/docs/README.md +44 -0
  8. data/docs/bulk_indexing.md +3 -0
  9. data/docs/client.md +240 -0
  10. data/docs/cluster.md +148 -0
  11. data/docs/docs.md +254 -0
  12. data/docs/index.md +161 -0
  13. data/docs/multi_search.md +3 -0
  14. data/docs/notifications.md +24 -11
  15. data/docs/scan_scroll.md +3 -0
  16. data/docs/snapshots.md +3 -0
  17. data/docs/templates.md +3 -0
  18. data/docs/warmers.md +3 -0
  19. data/elastomer-client.gemspec +2 -2
  20. data/lib/elastomer/client.rb +70 -43
  21. data/lib/elastomer/client/bulk.rb +2 -2
  22. data/lib/elastomer/client/cluster.rb +2 -2
  23. data/lib/elastomer/client/docs.rb +190 -54
  24. data/lib/elastomer/client/errors.rb +4 -2
  25. data/lib/elastomer/client/index.rb +111 -43
  26. data/lib/elastomer/client/multi_search.rb +1 -1
  27. data/lib/elastomer/client/nodes.rb +9 -4
  28. data/lib/elastomer/client/repository.rb +2 -2
  29. data/lib/elastomer/client/scroller.rb +235 -0
  30. data/lib/elastomer/client/snapshot.rb +1 -1
  31. data/lib/elastomer/client/template.rb +1 -1
  32. data/lib/elastomer/client/warmer.rb +1 -1
  33. data/lib/elastomer/notifications.rb +1 -1
  34. data/lib/elastomer/version.rb +1 -1
  35. data/script/bootstrap +0 -7
  36. data/script/cibuild +8 -3
  37. data/script/test +6 -0
  38. data/test/client/bulk_test.rb +2 -2
  39. data/test/client/cluster_test.rb +23 -2
  40. data/test/client/docs_test.rb +137 -6
  41. data/test/client/errors_test.rb +12 -8
  42. data/test/client/index_test.rb +88 -5
  43. data/test/client/multi_search_test.rb +29 -0
  44. data/test/client/repository_test.rb +36 -37
  45. data/test/client/{scan_test.rb → scroller_test.rb} +25 -6
  46. data/test/client/snapshot_test.rb +53 -43
  47. data/test/client/stubbed_client_test.rb +1 -1
  48. data/test/client_test.rb +60 -0
  49. data/test/notifications_test.rb +69 -0
  50. data/test/test_helper.rb +54 -11
  51. metadata +36 -23
  52. data/.ruby-version +0 -1
  53. data/lib/elastomer/client/scan.rb +0 -161
  54. data/script/testsuite +0 -10
@@ -35,7 +35,7 @@ module Elastomer
35
35
  raise exception
36
36
  end
37
37
  end
38
- alias :exist? :exists?
38
+ alias_method :exist?, :exists?
39
39
 
40
40
  # Create the repository.
41
41
  # See http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-snapshots.html#_repositories
@@ -103,7 +103,7 @@ module Elastomer
103
103
  def snapshot(snapshot = nil)
104
104
  client.snapshot(name, snapshot)
105
105
  end
106
- alias :snapshots :snapshot
106
+ alias_method :snapshots, :snapshot
107
107
 
108
108
  # Internal: Add default parameters to the `params` Hash and then apply
109
109
  # `overrides` to the params if any are given.
@@ -0,0 +1,235 @@
1
+ module Elastomer
2
+ class Client
3
+
4
+ # Create a new Scroller instance for scrolling all results from a `query`.
5
+ #
6
+ # query - The query to scroll as a Hash or a JSON encoded String
7
+ # opts - Options Hash
8
+ # :index - the name of the index to search
9
+ # :type - the document type to search
10
+ # :scroll - the keep alive time of the scrolling request (5 minutes by default)
11
+ # :size - the number of documents per shard to fetch per scroll
12
+ #
13
+ # Examples
14
+ #
15
+ # scroll = client.scroll('{"query":{"match_all":{}}}', :index => 'test')
16
+ # scroll.each_document do |document|
17
+ # document['_id']
18
+ # document['_source']
19
+ # end
20
+ #
21
+ # Returns a new Scroller instance
22
+ def scroll( query, opts = {} )
23
+ Scroller.new(self, query, opts)
24
+ end
25
+
26
+ # Create a new Scroller instance for scrolling all results from a `query`
27
+ # via "scan" semantics.
28
+ #
29
+ # query - The query to scan as a Hash or a JSON encoded String
30
+ # opts - Options Hash
31
+ # :index - the name of the index to search
32
+ # :type - the document type to search
33
+ # :scroll - the keep alive time of the scrolling request (5 minutes by default)
34
+ # :size - the number of documents per shard to fetch per scroll
35
+ #
36
+ # Examples
37
+ #
38
+ # scan = client.scan('{"query":{"match_all":{}}}', :index => 'test')
39
+ # scan.each_document do |document|
40
+ # document['_id']
41
+ # document['_source']
42
+ # end
43
+ #
44
+ # Returns a new Scroller instance
45
+ def scan( query, opts = {} )
46
+ opts = opts.merge(:search_type => 'scan')
47
+ Scroller.new(self, query, opts)
48
+ end
49
+
50
+ # Begin scrolling a query.
51
+ # See http://www.elasticsearch.org/guide/reference/api/search/scroll/
52
+ #
53
+ # opts - Options Hash
54
+ # :query - the query to scroll as a Hash or JSON encoded String
55
+ # :index - the name of the index to search
56
+ # :type - the document type to search
57
+ # :scroll - the keep alive time of the scrolling request (5 minutes by default)
58
+ # :size - the number of documents per shard to fetch per scroll
59
+ # :search_type - set to 'scan' for scan semantics
60
+ #
61
+ # Examples
62
+ #
63
+ # h = client.start_scroll('{"query":{"match_all":{}},"sort":{"created":"desc"}}', :index => 'test')
64
+ # scroll_id = h['_scroll_id']
65
+ # h['hits']['hits'].each { |doc| ... }
66
+ #
67
+ # h = client.continue_scroll(scroll_id)
68
+ # scroll_id = h['_scroll_id']
69
+ # h['hits']['hits'].each { |doc| ... }
70
+ #
71
+ # # repeat until there are no more hits
72
+ #
73
+ # Returns the response body as a Hash.
74
+ def start_scroll( opts = {} )
75
+ opts = opts.merge :action => 'search.start_scroll'
76
+ response = get '{/index}{/type}/_search', opts
77
+ response.body
78
+ end
79
+
80
+ # Continue scrolling a query.
81
+ # See http://www.elasticsearch.org/guide/reference/api/search/scroll/
82
+ #
83
+ # scroll_id - The current scroll ID as a String
84
+ # scroll - The keep alive time of the scrolling request (5 minutes by default)
85
+ #
86
+ # Examples
87
+ #
88
+ # scroll_id = client.start_scroll('{"query":{"match_all":{}}}', :index => 'test', :search_type => 'scan')['_scroll_id']
89
+ #
90
+ # h = client.continue_scroll scroll_id # scroll to get the next set of results
91
+ # scroll_id = h['_scroll_id'] # and store the scroll_id to use later
92
+ #
93
+ # h = client.continue_scroll scroll_id # scroll again to get the next set of results
94
+ # scroll_id = h['_scroll_id'] # and store the scroll_id to use later
95
+ #
96
+ # # repeat until the results are empty
97
+ #
98
+ # Returns the response body as a Hash.
99
+ def continue_scroll( scroll_id, scroll = '5m' )
100
+ response = get '/_search/scroll', :body => scroll_id, :scroll => scroll, :action => 'search.scroll'
101
+ response.body
102
+ end
103
+
104
+ class Scroller
105
+ # Create a new scroller that can be used to iterate over all the documents
106
+ # returned by the `query`. The Scroller supports both the 'scan' and the
107
+ # 'scroll' search types.
108
+ #
109
+ # See http://www.elasticsearch.org/guide/reference/api/search/scroll/
110
+ # and the "Scan" section of http://www.elasticsearch.org/guide/reference/api/search/search-type/
111
+ #
112
+ # client - Elastomer::Client used for HTTP requests to the server
113
+ # query - The query to scan as a Hash or a JSON encoded String
114
+ # opts - Options Hash
115
+ # :index - the name of the index to search
116
+ # :type - the document type to search
117
+ # :scroll - the keep alive time of the scrolling request (5 minutes by default)
118
+ # :size - the number of documents per shard to fetch per scroll
119
+ # :search_type - set to 'scan' for scan query semantics
120
+ #
121
+ # Examples
122
+ #
123
+ # scan = Scroller.new(client, {:search_type => 'scan', :query => {:match_all => {}}}, :index => 'test-1')
124
+ # scan.each_document { |doc|
125
+ # doc['_id']
126
+ # doc['_source']
127
+ # }
128
+ #
129
+ def initialize( client, query, opts = {} )
130
+ @client = client
131
+ @query = query
132
+
133
+ @index = opts.fetch(:index, nil)
134
+ @type = opts.fetch(:type, nil)
135
+ @scroll = opts.fetch(:scroll, '5m')
136
+ @size = opts.fetch(:size, 50)
137
+ @search_type = opts.fetch(:search_type, nil)
138
+
139
+ @scroll_id = nil
140
+ @offset = 0
141
+ end
142
+
143
+ attr_reader :client, :query, :index, :type, :scroll, :size, :search_type, :scroll_id
144
+
145
+ # Iterate over all the search results from the scan query.
146
+ #
147
+ # block - The block will be called for each set of matching documents
148
+ # returned from executing the scan query.
149
+ #
150
+ # Yields a hits Hash containing the 'total' number of hits, current
151
+ # 'offset' into that total, and the Array of 'hits' document Hashes.
152
+ #
153
+ # Examples
154
+ #
155
+ # scan.each do |hits|
156
+ # hits['total']
157
+ # hits['offset']
158
+ # hits['hits'].each { |document| ... }
159
+ # end
160
+ #
161
+ # Returns this Scan instance.
162
+ def each
163
+ loop do
164
+ body = do_scroll
165
+
166
+ hits = body['hits']
167
+ break if hits['hits'].empty?
168
+
169
+ hits['offset'] = @offset
170
+ @offset += hits['hits'].length
171
+
172
+ yield hits
173
+ end
174
+
175
+ self
176
+ end
177
+
178
+ # Iterate over each document from the scan query. This method is just a
179
+ # convenience wrapper around the `each` method; it iterates the Array of
180
+ # documents and passes them one by one to the block.
181
+ #
182
+ # block - The block will be called for each document returned from
183
+ # executing the scan query.
184
+ #
185
+ # Yields a document Hash.
186
+ #
187
+ # Examples
188
+ #
189
+ # scan.each_document do |document|
190
+ # document['_id']
191
+ # document['_source']
192
+ # end
193
+ #
194
+ # Returns this Scan instance.
195
+ def each_document( &block )
196
+ each { |hits| hits['hits'].each(&block) }
197
+ end
198
+
199
+ # Internal: Perform the actual scroll requests. This method wil call out
200
+ # to the `Client#start_scroll` and `Client#continue_scroll` methods while
201
+ # keeping track of the `scroll_id` internally.
202
+ #
203
+ # Returns the response body as a Hash.
204
+ def do_scroll
205
+ if scroll_id.nil?
206
+ body = client.start_scroll(scroll_opts)
207
+ if body['hits']['hits'].empty?
208
+ @scroll_id = body['_scroll_id']
209
+ return do_scroll
210
+ end
211
+ else
212
+ body = client.continue_scroll(scroll_id, scroll)
213
+ end
214
+
215
+ @scroll_id = body['_scroll_id']
216
+ body
217
+ end
218
+
219
+ # Internal: Returns the options Hash that should be passed to the initial
220
+ # `Client#start_scroll` method call.
221
+ def scroll_opts
222
+ hash = {
223
+ :scroll => scroll,
224
+ :size => size,
225
+ :index => index,
226
+ :type => type,
227
+ :body => query
228
+ }
229
+ hash[:search_type] = search_type unless search_type.nil?
230
+ hash
231
+ end
232
+
233
+ end # Scroller
234
+ end # Client
235
+ end # Elastomer
@@ -44,7 +44,7 @@ module Elastomer
44
44
  raise exception
45
45
  end
46
46
  end
47
- alias :exist? :exists?
47
+ alias_method :exist?, :exists?
48
48
 
49
49
  # Create the snapshot.
50
50
  # See http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-snapshots.html#_snapshot
@@ -27,7 +27,7 @@ module Elastomer
27
27
  def exists?
28
28
  client.cluster.templates.key? name
29
29
  end
30
- alias :exist? :exists?
30
+ alias_method :exist?, :exists?
31
31
 
32
32
  # Get the template from the cluster.
33
33
  # See http://www.elasticsearch.org/guide/reference/api/admin-indices-templates/
@@ -85,7 +85,7 @@ module Elastomer
85
85
  raise exception
86
86
  end
87
87
  end
88
- alias :exist? :exists?
88
+ alias_method :exist?, :exists?
89
89
 
90
90
  # Internal: Returns a Hash containing default parameters.
91
91
  def defaults
@@ -72,7 +72,7 @@ module Elastomer
72
72
  end
73
73
  end
74
74
 
75
- # use ActiveSupport::Notifications as the default instrumentaiton service
75
+ # use ActiveSupport::Notifications as the default instrumentation service
76
76
  Notifications.service = ActiveSupport::Notifications
77
77
 
78
78
  # inject our instrument method into the Client class
@@ -1,5 +1,5 @@
1
1
  module Elastomer
2
- VERSION = '0.4.1'
2
+ VERSION = '0.5.0'
3
3
 
4
4
  def self.version
5
5
  VERSION
data/script/bootstrap CHANGED
@@ -1,13 +1,6 @@
1
1
  #!/bin/sh
2
2
  set -e
3
3
 
4
- # force use of gcc under mac due to hiredis issues under clang
5
- if [ $(uname) = Darwin ]; then
6
- export CC=/usr/bin/gcc
7
- export CXX=/usr/bin/g++
8
- export LD=/usr/bin/gcc
9
- fi
10
-
11
4
  cd "$(dirname "$0")/.."
12
5
  if bundle check 1>/dev/null 2>&1; then
13
6
  echo "Gem environment up-to-date"
data/script/cibuild CHANGED
@@ -12,12 +12,17 @@ PATH="$(pwd)/bin:$(pwd)/script:/usr/share/rbenv/shims:$PATH"
12
12
  git log -n 1 || true
13
13
  echo
14
14
 
15
+ # Create a snapshot dir and make it world writable
16
+ export SNAPSHOT_DIR=/tmp/elastomer-client-snapshot-test
17
+ mkdir -p $SNAPSHOT_DIR
18
+ chmod a+rw $SNAPSHOT_DIR
19
+
15
20
  result=0
16
21
 
17
- export RBENV_VERSION="$(cat .ruby-version)"
18
- echo "Building under $RBENV_VERSION"
22
+ export RBENV_VERSION="2.1.1-github"
23
+ ruby -v
19
24
  script/bootstrap
20
- script/testsuite || result=$?
25
+ script/test || result=$?
21
26
 
22
27
  if [ $result -ne 0 ]; then
23
28
  exit $result
data/script/test ADDED
@@ -0,0 +1,6 @@
1
+ #!/bin/sh
2
+ set -e
3
+ cd "$(dirname "$0")/.."
4
+
5
+ fn=${1:-"test/**/*_test.rb"}
6
+ bundle exec testrb -Itest $fn $@
@@ -91,7 +91,7 @@ describe Elastomer::Client::Bulk do
91
91
  assert_bulk_create h['items'].last
92
92
 
93
93
  book_id = items.last['create']['_id']
94
- assert_match %r/^\S{22}$/, book_id
94
+ assert_match %r/^\S{20,22}$/, book_id
95
95
 
96
96
  @index.refresh
97
97
 
@@ -112,7 +112,7 @@ describe Elastomer::Client::Bulk do
112
112
  assert_bulk_delete h['items'].last, 'expected to delete a book'
113
113
 
114
114
  book_id2 = items.first['create']['_id']
115
- assert_match %r/^\S{22}$/, book_id2
115
+ assert_match %r/^\S{20,22}$/, book_id2
116
116
 
117
117
  @index.refresh
118
118
 
@@ -43,6 +43,12 @@ describe Elastomer::Client::Cluster do
43
43
  end
44
44
 
45
45
  it 'gets the cluster settings' do
46
+ h = @cluster.get_settings
47
+ assert_instance_of Hash, h['persistent'], 'the persistent settings are returned'
48
+ assert_instance_of Hash, h['transient'], 'the transient settings are returned'
49
+ end
50
+
51
+ it 'gets the cluster settings with .settings' do
46
52
  h = @cluster.settings
47
53
  assert_instance_of Hash, h['persistent'], 'the persistent settings are returned'
48
54
  assert_instance_of Hash, h['transient'], 'the transient settings are returned'
@@ -105,9 +111,11 @@ describe Elastomer::Client::Cluster do
105
111
  @index.delete if @index.exists?
106
112
  end
107
113
 
108
- it 'adds an alias' do
114
+ it 'adds and gets an alias' do
109
115
  hash = @cluster.get_aliases
110
- assert_empty hash[@name]['aliases']
116
+ if es_version_always_returns_aliases?
117
+ assert_empty hash[@name]['aliases']
118
+ end
111
119
 
112
120
  @cluster.update_aliases \
113
121
  :add => {:index => @name, :alias => 'elastomer-test-unikitty'}
@@ -116,6 +124,19 @@ describe Elastomer::Client::Cluster do
116
124
  assert_equal ['elastomer-test-unikitty'], hash[@name]['aliases'].keys
117
125
  end
118
126
 
127
+ it 'adds and gets an alias with .aliases' do
128
+ hash = @cluster.aliases
129
+ if es_version_always_returns_aliases?
130
+ assert_empty hash[@name]['aliases']
131
+ end
132
+
133
+ @cluster.update_aliases \
134
+ :add => {:index => @name, :alias => 'elastomer-test-unikitty'}
135
+
136
+ hash = @cluster.aliases
137
+ assert_equal ['elastomer-test-unikitty'], hash[@name]['aliases'].keys
138
+ end
139
+
119
140
  it 'removes an alias' do
120
141
  @cluster.update_aliases \
121
142
  :add => {:index => @name, :alias => 'elastomer-test-unikitty'}
@@ -20,7 +20,7 @@ describe Elastomer::Client::Docs do
20
20
  :doc2 => {
21
21
  :_source => { :enabled => true }, :_all => { :enabled => false },
22
22
  :properties => {
23
- :title => { :type => 'string', :analyzer => 'standard' },
23
+ :title => { :type => 'string', :analyzer => 'standard', :term_vector => 'with_positions_offsets' },
24
24
  :author => { :type => 'string', :index => 'not_analyzed' }
25
25
  }
26
26
  }
@@ -43,7 +43,7 @@ describe Elastomer::Client::Docs do
43
43
  :author => 'pea53'
44
44
 
45
45
  assert_created h
46
- assert_match %r/^\S{22}$/, h['_id']
46
+ assert_match %r/^\S{20,22}$/, h['_id']
47
47
 
48
48
  h = @docs.index \
49
49
  :_id => nil,
@@ -52,7 +52,7 @@ describe Elastomer::Client::Docs do
52
52
  :author => 'grantr'
53
53
 
54
54
  assert_created h
55
- assert_match %r/^\S{22}$/, h['_id']
55
+ assert_match %r/^\S{20,22}$/, h['_id']
56
56
 
57
57
  h = @docs.index \
58
58
  :_id => '',
@@ -61,7 +61,7 @@ describe Elastomer::Client::Docs do
61
61
  :author => 'mojombo'
62
62
 
63
63
  assert_created h
64
- assert_match %r/^\S{22}$/, h['_id']
64
+ assert_match %r/^\S{20,22}$/, h['_id']
65
65
  end
66
66
 
67
67
  it 'uses the provided document ID' do
@@ -89,7 +89,29 @@ describe Elastomer::Client::Docs do
89
89
  :type => 'doc2'
90
90
 
91
91
  assert_created h
92
- assert_match %r/^\S{22}$/, h['_id']
92
+ assert_match %r/^\S{20,22}$/, h['_id']
93
+ end
94
+
95
+ it 'extracts underscore attributes from the document' do
96
+ doc = {
97
+ :_id => '12',
98
+ :_type => 'doc2',
99
+ :_routing => 'author',
100
+ '_consistency' => 'all',
101
+ :title => "The Adventures of Huckleberry Finn",
102
+ :author => "Mark Twain",
103
+ :_unknown => "unknown attribute"
104
+ }
105
+
106
+ h = @docs.index doc
107
+ assert_created h
108
+ assert_equal '12', h['_id']
109
+
110
+ refute doc.key?(:_id)
111
+ refute doc.key?(:_type)
112
+ refute doc.key?(:_routing)
113
+ refute doc.key?('_consistency')
114
+ assert doc.key?(:_unknown)
93
115
  end
94
116
 
95
117
  it 'gets documents from the search index' do
@@ -103,6 +125,18 @@ describe Elastomer::Client::Docs do
103
125
  assert_equal 'mojombo', h['_source']['author']
104
126
  end
105
127
 
128
+ it 'checks if documents exist in the search index' do
129
+ refute @docs.exists?(:id => '1', :type => 'doc1')
130
+ populate!
131
+ assert @docs.exists?(:id => '1', :type => 'doc1')
132
+ end
133
+
134
+ it 'checks if documents exist in the search index with .exist?' do
135
+ refute @docs.exist?(:id => '1', :type => 'doc1')
136
+ populate!
137
+ assert @docs.exist?(:id => '1', :type => 'doc1')
138
+ end
139
+
106
140
  it 'gets multiple documents from the search index' do
107
141
  populate!
108
142
 
@@ -113,7 +147,7 @@ describe Elastomer::Client::Docs do
113
147
  authors = h['docs'].map { |d| d['_source']['author'] }
114
148
  assert_equal %w[mojombo pea53], authors
115
149
 
116
- h = @docs.multi_get :ids => [2, 1], :_type => 'doc1'
150
+ h = @docs.multi_get({:ids => [2, 1]}, :type => 'doc1')
117
151
  authors = h['docs'].map { |d| d['_source']['author'] }
118
152
  assert_equal %w[defunkt mojombo], authors
119
153
 
@@ -124,6 +158,27 @@ describe Elastomer::Client::Docs do
124
158
  refute_found h['docs'][3]
125
159
  end
126
160
 
161
+ it 'gets multiple documents from the search index with .mget' do
162
+ populate!
163
+
164
+ h = @docs.mget :docs => [
165
+ { :_id => 1, :_type => 'doc1' },
166
+ { :_id => 1, :_type => 'doc2' }
167
+ ]
168
+ authors = h['docs'].map { |d| d['_source']['author'] }
169
+ assert_equal %w[mojombo pea53], authors
170
+
171
+ h = @docs.mget({:ids => [2, 1]}, :type => 'doc1')
172
+ authors = h['docs'].map { |d| d['_source']['author'] }
173
+ assert_equal %w[defunkt mojombo], authors
174
+
175
+ h = @index.docs('doc1').mget :ids => [1, 2, 3, 4]
176
+ assert_found h['docs'][0]
177
+ assert_found h['docs'][1]
178
+ refute_found h['docs'][2]
179
+ refute_found h['docs'][3]
180
+ end
181
+
127
182
  it 'deletes documents from the search index' do
128
183
  populate!
129
184
  @docs = @index.docs('doc2')
@@ -207,6 +262,16 @@ describe Elastomer::Client::Docs do
207
262
  assert_equal 'the author of resque', hit['_source']['title']
208
263
  end
209
264
 
265
+ it 'supports the shards search API' do
266
+ if es_version_supports_search_shards?
267
+ h = @docs.search_shards(:type => 'docs1')
268
+
269
+ assert h.key?("nodes"), "response contains \"nodes\" information"
270
+ assert h.key?("shards"), "response contains \"shards\" information"
271
+ assert h["shards"].is_a?(Array), "\"shards\" is an array"
272
+ end
273
+ end
274
+
210
275
  it 'counts documents' do
211
276
  h = @docs.count :q => '*:*'
212
277
  assert_equal 0, h['count']
@@ -375,6 +440,72 @@ describe Elastomer::Client::Docs do
375
440
  assert_equal 'mojombo', response['_source']['author']
376
441
  end
377
442
 
443
+ if es_version_1_x?
444
+ it 'provides access to term vector statistics' do
445
+ populate!
446
+
447
+ response = @docs.termvector :type => 'doc2', :id => 1, :fields => 'title'
448
+
449
+ assert response['term_vectors']['title']
450
+ assert response['term_vectors']['title']['field_statistics']
451
+ assert response['term_vectors']['title']['terms']
452
+ assert_equal %w[author logging of the], response['term_vectors']['title']['terms'].keys
453
+ end
454
+
455
+ it 'provides access to term vector statistics with .termvectors' do
456
+ populate!
457
+
458
+ response = @docs.termvectors :type => 'doc2', :id => 1, :fields => 'title'
459
+
460
+ assert response['term_vectors']['title']
461
+ assert response['term_vectors']['title']['field_statistics']
462
+ assert response['term_vectors']['title']['terms']
463
+ assert_equal %w[author logging of the], response['term_vectors']['title']['terms'].keys
464
+ end
465
+
466
+ it 'provides access to term vector statistics with .term_vector' do
467
+ populate!
468
+
469
+ response = @docs.term_vector :type => 'doc2', :id => 1, :fields => 'title'
470
+
471
+ assert response['term_vectors']['title']
472
+ assert response['term_vectors']['title']['field_statistics']
473
+ assert response['term_vectors']['title']['terms']
474
+ assert_equal %w[author logging of the], response['term_vectors']['title']['terms'].keys
475
+ end
476
+
477
+ it 'provides access to term vector statistics with .term_vectors' do
478
+ populate!
479
+
480
+ response = @docs.term_vectors :type => 'doc2', :id => 1, :fields => 'title'
481
+
482
+ assert response['term_vectors']['title']
483
+ assert response['term_vectors']['title']['field_statistics']
484
+ assert response['term_vectors']['title']['terms']
485
+ assert_equal %w[author logging of the], response['term_vectors']['title']['terms'].keys
486
+ end
487
+
488
+ it 'provides access to multi term vector statistics' do
489
+ populate!
490
+
491
+ response = @docs.multi_termvectors({:ids => [1, 2]}, :type => 'doc2', :fields => 'title', :term_statistics => true)
492
+ docs = response['docs']
493
+
494
+ assert docs
495
+ assert_equal(%w[1 2], docs.map { |h| h['_id'] }.sort)
496
+ end
497
+
498
+ it 'provides access to multi term vector statistics with .multi_term_vectors' do
499
+ populate!
500
+
501
+ response = @docs.multi_term_vectors({:ids => [1, 2]}, :type => 'doc2', :fields => 'title', :term_statistics => true)
502
+ docs = response['docs']
503
+
504
+ assert docs
505
+ assert_equal(%w[1 2], docs.map { |h| h['_id'] }.sort)
506
+ end
507
+ end
508
+
378
509
  # Create/index multiple documents.
379
510
  #
380
511
  # docs - An instance of Elastomer::Client::Docs or Elastomer::Client::Bulk. If