stretcher 1.15.0 → 1.16.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 40ad9ca446b66da2b1558340d83accb106dd80bc
4
+ data.tar.gz: bc711b243bd448dbe5cb7079ad32353ef1244378
5
+ SHA512:
6
+ metadata.gz: 41acaea45c9f4ec37fcd736c4ba7dab2929ffcb39b06a4134c7db3a84b843e923c529113b08f29d5b98142a1d9e013a8c23238498cd3d6d7e5074702a8c071ae
7
+ data.tar.gz: f00e4c5f5beaa2645680fdeff3182c4fd3b708981c15647ef2096ddad2a3ae84ea5ef959d0ccf3de8317e514806a756e5fc0dc5cc085098a09d3767f2d4e41a2
data/README.md CHANGED
@@ -14,6 +14,7 @@ A concise, fast ElasticSearch client designed to reflect the actual elastic sear
14
14
  * Supports efficient bulk indexing operations
15
15
  * Returns most responses in convenient Hashie::Mash form
16
16
  * Configurable logging
17
+ * Logs curl commandline statements in debug mode
17
18
  * Pure, threadsafe, ruby
18
19
  * Easily swap HTTP clients via Faraday
19
20
  * Tested against Ruby 2.0,1.9,1.8.7, Jruby, and Rubinius
@@ -86,6 +87,20 @@ server.index(:foo).bulk_index(docs)
86
87
 
87
88
  This README documents only part of stretcher's API. The full documentation for stretcher is available in its [full rdocs](http://rdoc.info/github/PoseBiz/stretcher/master/frames).
88
89
 
90
+ ### Logging
91
+
92
+ Pass in the the `:log_level` parameter to set logging verbosity. cURL statements are surfaced at the `:debug` log level. For instance:
93
+
94
+ ```ruby
95
+ Stretcher::Server.new('http://localhost:9200', :log_level => :debug)
96
+ ```
97
+
98
+ You can also pass any Logger style object with the `:logger` option. For instance:
99
+
100
+ ```ruby
101
+ Stretcher::Server.new('http://localhost:9200', :logger => Rails.logger)
102
+ ```
103
+
89
104
  ### Rails Integration
90
105
 
91
106
  Stretcher is a low level-client, but it was built as a part of a full suite of Rails integration tools.
@@ -43,7 +43,7 @@ module Stretcher
43
43
 
44
44
  body = documents.reduce("") {|post_data, d_raw|
45
45
  d = Hashie::Mash.new(d_raw)
46
- index_meta = { :_index => name, :_id => (d.delete(:id) || d.delete(:_id)) }
46
+ index_meta = { :_index => name, :_id => (d[:id] || d.delete(:_id)) }
47
47
 
48
48
  system_fields = %w{_type _parent _routing}
49
49
  d.keys.reduce(index_meta) do |memo, key|
@@ -67,6 +67,13 @@ module Stretcher
67
67
  request :delete
68
68
  end
69
69
 
70
+ # Takes a collection of hashes of the form {:_type => 'foo', :_id => 123}
71
+ # And issues an mget for them within the current index
72
+ def mget(meta_docs)
73
+ merge_data = {:_index => name}
74
+ @server.mget(meta_docs.map {|d| d.merge(merge_data) })
75
+ end
76
+
70
77
  # Retrieves stats for this index
71
78
  def stats
72
79
  request :get, "_stats"
@@ -36,6 +36,10 @@ module Stretcher
36
36
  request(:get, '_mget', options, :ids => ids)
37
37
  end
38
38
 
39
+ def mget_existing(ids,options={})
40
+ mget(ids, options)
41
+ end
42
+
39
43
  # Explains a query for a specific document
40
44
  def explain(id, query, options={})
41
45
  request(:get, "#{id}/_explain", options, query)
@@ -38,12 +38,16 @@ module Stretcher
38
38
  # Builds a logger when initializing an instance
39
39
  def self.build_logger(options)
40
40
  logger = options[:logger] || Logger.new(STDOUT)
41
- log_level = options[:log_level] || :debug
42
- logger.level = Logger.const_get(log_level.to_s.upcase)
43
41
 
44
- logger.formatter = proc do |severity, datetime, progname, msg|
45
- "[Stretcher][#{severity}]: #{msg}\n"
42
+ # We don't want to override the formatter if an external logger is used
43
+ if !options[:logger]
44
+ log_level = options[:log_level] || :warn
45
+ logger.level = Logger.const_get(log_level.to_s.upcase)
46
+ logger.formatter = proc do |severity, datetime, progname, msg|
47
+ "[Stretcher][#{severity}]: #{msg}\n"
48
+ end
46
49
  end
50
+
47
51
  logger
48
52
  end
49
53
 
@@ -134,11 +138,28 @@ module Stretcher
134
138
  end
135
139
 
136
140
  # Retrieves multiple documents, possibly from multiple indexes
141
+ # Takes an array of docs, returns an array of docs
137
142
  # as per: http://www.elasticsearch.org/guide/reference/api/multi-get.html
138
- def mget(body={})
139
- request(:get, path_uri("/_mget")) {|req|
140
- req.body = body
141
- }
143
+ # If you pass :exists => true as the second argument it will not return stubs
144
+ # for missing documents. :exists => false works in reverse
145
+ def mget(docs=[], arg_opts={})
146
+ #Legacy API
147
+ return legacy_mget(docs) if docs.is_a?(Hash)
148
+
149
+ opts = {:exists => true}.merge(arg_opts)
150
+
151
+ res = request(:get, path_uri("/_mget"), {}, {:docs => docs})[:docs]
152
+ if opts.has_key?(:exists)
153
+ match = opts[:exists]
154
+ res.select {|d| d[:exists] == match}
155
+ else
156
+ res
157
+ end
158
+ end
159
+
160
+ # legacy implementation of mget for backwards compat
161
+ def legacy_mget(body)
162
+ request(:get, path_uri("/_mget"), {}, body)
142
163
  end
143
164
 
144
165
  # Implements the Analyze API
@@ -1,3 +1,3 @@
1
1
  module Stretcher
2
- VERSION = "1.15.0"
2
+ VERSION = "1.16.0"
3
3
  end
@@ -27,7 +27,10 @@ describe Stretcher::Index do
27
27
  [
28
28
  {:text => "Foo", :_text => '_Foo', "_type" => 'tweet', "_id" => 'fooid'},
29
29
  {:text => "Bar", :_text => '_Bar', "_type" => 'tweet', "_id" => 'barid'},
30
- {:text => "Baz", :_text => '_Baz', "_type" => 'tweet', "id" => 'bazid'} # Note we support both _id and id
30
+ {:text => "Baz", :_text => '_Baz', "_type" => 'tweet', "id" => 'bazid'}, # Note we support both _id and id
31
+ {:username => "john", :age => 25, "_type" => 'user', "_id" => 'fooid'},
32
+ {:username => "jacob", :age => 32, "_type" => 'user', "_id" => 'barid'},
33
+ {:username => "jingleheimer", :age => 54, "_type" => 'user', "id" => 'bazid'} # Note we support both _id and id
31
34
  ]
32
35
  }
33
36
 
@@ -36,8 +39,15 @@ describe Stretcher::Index do
36
39
  index.type(:tweet).put_mapping(mdata)
37
40
  end
38
41
 
42
+ def create_user_mapping
43
+ mdata = {:user => {:properties => {:username => {:type => :string},
44
+ :age => {:type => :integer}}}}
45
+ index.type(:user).put_mapping(mdata)
46
+ end
47
+
39
48
  def seed_corpus
40
49
  create_tweet_mapping
50
+ create_user_mapping
41
51
  index.bulk_index(corpus)
42
52
  index.refresh
43
53
  end
@@ -48,7 +58,7 @@ describe Stretcher::Index do
48
58
  options = { :mappings => { :movie => { :properties => { :category => { :type => 'string' } } } } }
49
59
 
50
60
  server.logger.should_receive(:debug) do |&block|
51
- block.call.should == %{curl -XPUT http://localhost:9200/foo -d '#{options.to_json}' '-H Accept: application/json' '-H Content-Type: application/json' '-H User-Agent: Stretcher Ruby Gem 1.14.0'}
61
+ block.call.should == %{curl -XPUT http://localhost:9200/foo -d '#{options.to_json}' '-H Accept: application/json' '-H Content-Type: application/json' '-H User-Agent: Stretcher Ruby Gem #{Stretcher::VERSION}'}
52
62
  end
53
63
 
54
64
  index.create(options)
@@ -71,6 +81,17 @@ describe Stretcher::Index do
71
81
  exposed.class.should == Stretcher::IndexType
72
82
  end
73
83
 
84
+ it "should return docs across types when issuing an mget" do
85
+ seed_corpus
86
+ tweet = corpus.select {|d| d['_type'] == 'tweet' }.first
87
+ user = corpus.select {|d| d['_type'] == 'user' }.first
88
+ res = index.mget([{:_type => 'tweet', :_id => (tweet["_id"] || tweet['id'])},
89
+ {:_type => 'user', :_id => (user["_id"] || user['id']) }])
90
+ res.length.should == 2
91
+ equalizer = lambda {|r| [r['_type'], r['_id']] }
92
+ res.map {|d| equalizer.call(d)}.sort.should == [tweet,user].map {|d| equalizer.call(d)}.sort
93
+ end
94
+
74
95
  it "should return stats without error" do
75
96
  index.stats['_all'].should_not be_nil
76
97
  end
@@ -102,13 +123,14 @@ describe Stretcher::Index do
102
123
 
103
124
  it "should bulk delete documents" do
104
125
  seed_corpus
105
- index.bulk_delete([
106
- {"_type" => 'tweet', "_id" => 'fooid'},
107
- {"_type" => 'tweet', "_id" => 'barid'},
108
- ])
126
+ docs_meta = [
127
+ {"_type" => 'tweet', "_id" => 'fooid'},
128
+ {"_type" => 'tweet', "_id" => 'barid'},
129
+ ]
130
+ index.mget(docs_meta).length.should == 2
131
+ index.bulk_delete(docs_meta)
109
132
  index.refresh
110
- res = index.search({}, {:query => {:match_all => {}}})
111
- expect(res.results.map(&:_id)).to match_array ['bazid']
133
+ res = index.mget(docs_meta).length.should == 0
112
134
  end
113
135
  end
114
136
 
data/stretcher.gemspec CHANGED
@@ -29,7 +29,7 @@ Gem::Specification.new do |gem|
29
29
  gem.add_dependency('faraday', '~> 0.8')
30
30
  gem.add_dependency('faraday_middleware', '~> 0.9.0')
31
31
  gem.add_dependency('excon', '>= 0.16')
32
- gem.add_dependency('hashie', '~> 1.2.0')
32
+ gem.add_dependency('hashie', '>= 1.2.0')
33
33
 
34
34
  gem.add_development_dependency 'rspec', '>= 2.5.0'
35
35
  gem.add_development_dependency 'coveralls'
metadata CHANGED
@@ -1,20 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stretcher
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.15.0
5
- prerelease:
4
+ version: 1.16.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Andrew Cholakian
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-06-20 00:00:00.000000000 Z
11
+ date: 2013-06-27 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: faraday
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
17
  - - ~>
20
18
  - !ruby/object:Gem::Version
@@ -22,7 +20,6 @@ dependencies:
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
24
  - - ~>
28
25
  - !ruby/object:Gem::Version
@@ -30,7 +27,6 @@ dependencies:
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: faraday_middleware
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
31
  - - ~>
36
32
  - !ruby/object:Gem::Version
@@ -38,7 +34,6 @@ dependencies:
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
38
  - - ~>
44
39
  - !ruby/object:Gem::Version
@@ -46,113 +41,99 @@ dependencies:
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: excon
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - '>='
52
46
  - !ruby/object:Gem::Version
53
47
  version: '0.16'
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - '>='
60
53
  - !ruby/object:Gem::Version
61
54
  version: '0.16'
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: hashie
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
- - - ~>
59
+ - - '>='
68
60
  - !ruby/object:Gem::Version
69
61
  version: 1.2.0
70
62
  type: :runtime
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
- - - ~>
66
+ - - '>='
76
67
  - !ruby/object:Gem::Version
77
68
  version: 1.2.0
78
69
  - !ruby/object:Gem::Dependency
79
70
  name: rspec
80
71
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
72
  requirements:
83
- - - ! '>='
73
+ - - '>='
84
74
  - !ruby/object:Gem::Version
85
75
  version: 2.5.0
86
76
  type: :development
87
77
  prerelease: false
88
78
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
79
  requirements:
91
- - - ! '>='
80
+ - - '>='
92
81
  - !ruby/object:Gem::Version
93
82
  version: 2.5.0
94
83
  - !ruby/object:Gem::Dependency
95
84
  name: coveralls
96
85
  requirement: !ruby/object:Gem::Requirement
97
- none: false
98
86
  requirements:
99
- - - ! '>='
87
+ - - '>='
100
88
  - !ruby/object:Gem::Version
101
89
  version: '0'
102
90
  type: :development
103
91
  prerelease: false
104
92
  version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
93
  requirements:
107
- - - ! '>='
94
+ - - '>='
108
95
  - !ruby/object:Gem::Version
109
96
  version: '0'
110
97
  - !ruby/object:Gem::Dependency
111
98
  name: simplecov
112
99
  requirement: !ruby/object:Gem::Requirement
113
- none: false
114
100
  requirements:
115
- - - ! '>='
101
+ - - '>='
116
102
  - !ruby/object:Gem::Version
117
103
  version: '0'
118
104
  type: :development
119
105
  prerelease: false
120
106
  version_requirements: !ruby/object:Gem::Requirement
121
- none: false
122
107
  requirements:
123
- - - ! '>='
108
+ - - '>='
124
109
  - !ruby/object:Gem::Version
125
110
  version: '0'
126
111
  - !ruby/object:Gem::Dependency
127
112
  name: vcr
128
113
  requirement: !ruby/object:Gem::Requirement
129
- none: false
130
114
  requirements:
131
- - - ! '>='
115
+ - - '>='
132
116
  - !ruby/object:Gem::Version
133
117
  version: '0'
134
118
  type: :development
135
119
  prerelease: false
136
120
  version_requirements: !ruby/object:Gem::Requirement
137
- none: false
138
121
  requirements:
139
- - - ! '>='
122
+ - - '>='
140
123
  - !ruby/object:Gem::Version
141
124
  version: '0'
142
125
  - !ruby/object:Gem::Dependency
143
126
  name: rake
144
127
  requirement: !ruby/object:Gem::Requirement
145
- none: false
146
128
  requirements:
147
- - - ! '>='
129
+ - - '>='
148
130
  - !ruby/object:Gem::Version
149
131
  version: '0'
150
132
  type: :development
151
133
  prerelease: false
152
134
  version_requirements: !ruby/object:Gem::Requirement
153
- none: false
154
135
  requirements:
155
- - - ! '>='
136
+ - - '>='
156
137
  - !ruby/object:Gem::Version
157
138
  version: '0'
158
139
  description: The elegant ElasticSearch client
@@ -187,27 +168,26 @@ files:
187
168
  - stretcher.gemspec
188
169
  homepage: https://github.com/PoseBiz/stretcher
189
170
  licenses: []
171
+ metadata: {}
190
172
  post_install_message:
191
173
  rdoc_options: []
192
174
  require_paths:
193
175
  - lib
194
176
  required_ruby_version: !ruby/object:Gem::Requirement
195
- none: false
196
177
  requirements:
197
- - - ! '>='
178
+ - - '>='
198
179
  - !ruby/object:Gem::Version
199
180
  version: '0'
200
181
  required_rubygems_version: !ruby/object:Gem::Requirement
201
- none: false
202
182
  requirements:
203
- - - ! '>='
183
+ - - '>='
204
184
  - !ruby/object:Gem::Version
205
185
  version: '0'
206
186
  requirements: []
207
187
  rubyforge_project:
208
- rubygems_version: 1.8.23
188
+ rubygems_version: 2.0.2
209
189
  signing_key:
210
- specification_version: 3
190
+ specification_version: 4
211
191
  summary: The elegant ElasticSearch client, supporting persistent connections, and
212
192
  a clean DSL
213
193
  test_files: