stretcher 1.15.0 → 1.16.0

Sign up to get free protection for your applications and to get access to all the features.
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: