elastomer-client 0.4.1 → 0.5.0

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.
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