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 +7 -0
- data/README.md +15 -0
- data/lib/stretcher/index.rb +8 -1
- data/lib/stretcher/index_type.rb +4 -0
- data/lib/stretcher/server.rb +29 -8
- data/lib/stretcher/version.rb +1 -1
- data/spec/lib/stretcher_index_spec.rb +30 -8
- data/stretcher.gemspec +1 -1
- metadata +21 -41
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.
|
data/lib/stretcher/index.rb
CHANGED
@@ -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
|
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"
|
data/lib/stretcher/index_type.rb
CHANGED
@@ -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)
|
data/lib/stretcher/server.rb
CHANGED
@@ -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
|
-
|
45
|
-
|
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
|
-
|
139
|
-
|
140
|
-
|
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
|
data/lib/stretcher/version.rb
CHANGED
@@ -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
|
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
|
-
|
106
|
-
|
107
|
-
|
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.
|
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', '
|
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.
|
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-
|
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:
|
188
|
+
rubygems_version: 2.0.2
|
209
189
|
signing_key:
|
210
|
-
specification_version:
|
190
|
+
specification_version: 4
|
211
191
|
summary: The elegant ElasticSearch client, supporting persistent connections, and
|
212
192
|
a clean DSL
|
213
193
|
test_files:
|