stretcher 1.4.0 → 1.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.
- data/README.md +1 -0
- data/lib/stretcher/es_component.rb +9 -3
- data/lib/stretcher/index.rb +5 -1
- data/lib/stretcher/index_type.rb +11 -2
- data/lib/stretcher/request_error.rb +4 -1
- data/lib/stretcher/search_results.rb +5 -3
- data/lib/stretcher/server.rb +5 -1
- data/lib/stretcher/util.rb +1 -1
- data/lib/stretcher/version.rb +1 -1
- data/spec/lib/stretcher_index_spec.rb +20 -2
- data/spec/lib/stretcher_index_type_spec.rb +46 -15
- metadata +2 -2
data/README.md
CHANGED
@@ -4,9 +4,9 @@ module Stretcher
|
|
4
4
|
|
5
5
|
# Many of the methods marked protected are called by one line shims in subclasses. This is mostly to facilitate
|
6
6
|
# better looking rdocs
|
7
|
-
|
7
|
+
|
8
8
|
private
|
9
|
-
|
9
|
+
|
10
10
|
def do_search(generic_opts={}, explicit_body=nil)
|
11
11
|
query_opts = {}
|
12
12
|
body = nil
|
@@ -21,7 +21,7 @@ module Stretcher
|
|
21
21
|
response = request(:get, "_search", query_opts) do |req|
|
22
22
|
req.body = body
|
23
23
|
end
|
24
|
-
SearchResults.new(:raw => response)
|
24
|
+
SearchResults.new(:raw => response)
|
25
25
|
end
|
26
26
|
|
27
27
|
def do_refresh
|
@@ -33,5 +33,11 @@ module Stretcher
|
|
33
33
|
raise "Cannot issue request, no server specified!" unless @server
|
34
34
|
@server.request(method, prefixed_path, query_opts, *args, &block)
|
35
35
|
end
|
36
|
+
|
37
|
+
def do_delete_query(query)
|
38
|
+
request :delete, '_query' do |req|
|
39
|
+
req.body = query
|
40
|
+
end
|
41
|
+
end
|
36
42
|
end
|
37
43
|
end
|
data/lib/stretcher/index.rb
CHANGED
@@ -78,6 +78,10 @@ module Stretcher
|
|
78
78
|
false
|
79
79
|
end
|
80
80
|
|
81
|
+
def delete_query(query)
|
82
|
+
do_delete_query(query)
|
83
|
+
end
|
84
|
+
|
81
85
|
# Issues a search with the given query opts and body, both should be hashes
|
82
86
|
#
|
83
87
|
# res = server.index('foo').search(size: 12, {query: {match_all: {}}})
|
@@ -117,7 +121,7 @@ module Stretcher
|
|
117
121
|
req.body = text
|
118
122
|
end
|
119
123
|
end
|
120
|
-
|
124
|
+
|
121
125
|
# Perform a refresh making all items in this index available instantly
|
122
126
|
def refresh
|
123
127
|
do_refresh
|
data/lib/stretcher/index_type.rb
CHANGED
@@ -13,6 +13,7 @@ module Stretcher
|
|
13
13
|
|
14
14
|
# Retrieves the document by ID
|
15
15
|
# Normally this returns the contents of _source, however, the 'raw' flag is passed in, it will return the full response hash
|
16
|
+
# Returns nil if the document does not exist
|
16
17
|
def get(id, raw=false)
|
17
18
|
res = request(:get, id)
|
18
19
|
raw ? res : res["_source"]
|
@@ -23,6 +24,11 @@ module Stretcher
|
|
23
24
|
request(:put, id, source)
|
24
25
|
end
|
25
26
|
|
27
|
+
# Index an item with automatic ID generation
|
28
|
+
def post(source)
|
29
|
+
request(:post, nil, source)
|
30
|
+
end
|
31
|
+
|
26
32
|
# Uses the update api to modify a document with a script
|
27
33
|
# To update a doc with ID 987 for example:
|
28
34
|
# type.update(987, script: "ctx._source.message = 'Updated!'")
|
@@ -63,11 +69,14 @@ module Stretcher
|
|
63
69
|
def exists?(id=nil)
|
64
70
|
request :head, id
|
65
71
|
true
|
66
|
-
rescue Stretcher::RequestError => e
|
67
|
-
raise e if e.http_response.status != 404
|
72
|
+
rescue Stretcher::RequestError::NotFound => e
|
68
73
|
false
|
69
74
|
end
|
70
75
|
|
76
|
+
def delete_query(query)
|
77
|
+
do_delete_query(query)
|
78
|
+
end
|
79
|
+
|
71
80
|
# Issues an Index#search scoped to this type
|
72
81
|
# See Index#search for more details
|
73
82
|
def search(generic_opts={}, explicit_body=nil)
|
@@ -2,9 +2,12 @@ module Stretcher
|
|
2
2
|
# Raised when the underlying http status of an operation != 200
|
3
3
|
class RequestError < StandardError
|
4
4
|
attr_reader :http_response
|
5
|
-
|
5
|
+
|
6
6
|
def initialize(http_response)
|
7
7
|
@http_response = http_response
|
8
8
|
end
|
9
|
+
|
10
|
+
class NotFound < RequestError
|
11
|
+
end
|
9
12
|
end
|
10
13
|
end
|
@@ -18,9 +18,11 @@ module Stretcher
|
|
18
18
|
super
|
19
19
|
self.total = raw.hits.total
|
20
20
|
self.facets = raw.facets
|
21
|
-
self.results = raw.hits.hits.collect
|
22
|
-
|
23
|
-
|
21
|
+
self.results = raw.hits.hits.collect do |r|
|
22
|
+
k = ['_source', 'fields'].detect { |k| r.key?(k) }
|
23
|
+
doc = k.nil? ? Hashie::Mash.new : r[k]
|
24
|
+
doc.merge({"_id" => r['_id']})
|
25
|
+
end
|
24
26
|
end
|
25
27
|
end
|
26
28
|
end
|
data/lib/stretcher/server.rb
CHANGED
@@ -119,7 +119,7 @@ module Stretcher
|
|
119
119
|
req.body = text
|
120
120
|
end
|
121
121
|
end
|
122
|
-
|
122
|
+
|
123
123
|
# Perform a refresh, making all indexed documents available
|
124
124
|
def refresh
|
125
125
|
do_refresh
|
@@ -146,6 +146,10 @@ module Stretcher
|
|
146
146
|
|
147
147
|
if res.status >= 200 && res.status <= 299
|
148
148
|
res.body
|
149
|
+
elsif res.status == 404
|
150
|
+
err_str = "Error 404 processing request: (#{res.status})! #{res.env[:method]} URL: #{res.env[:url]}"
|
151
|
+
err_str << "\n Resp Body: #{res.body}"
|
152
|
+
raise RequestError::NotFound.new(res), err_str
|
149
153
|
else
|
150
154
|
err_str = "Error processing request (#{res.status})! #{res.env[:method]} URL: #{res.env[:url]}"
|
151
155
|
err_str << "\n Resp Body: #{res.body}"
|
data/lib/stretcher/util.rb
CHANGED
data/lib/stretcher/version.rb
CHANGED
@@ -4,7 +4,16 @@ describe Stretcher::Index do
|
|
4
4
|
let(:server) {
|
5
5
|
Stretcher::Server.new(ES_URL, :logger => DEBUG_LOGGER)
|
6
6
|
}
|
7
|
-
let(:index) {
|
7
|
+
let(:index) {
|
8
|
+
i = server.index('foo')
|
9
|
+
i.delete
|
10
|
+
server.refresh
|
11
|
+
i.create
|
12
|
+
# Why do both? Doesn't hurt, and it fixes some races
|
13
|
+
server.refresh
|
14
|
+
i.refresh
|
15
|
+
i
|
16
|
+
}
|
8
17
|
let(:corpus) {
|
9
18
|
[
|
10
19
|
{:text => "Foo", "_type" => 'tweet', "_id" => 'fooid'},
|
@@ -21,6 +30,7 @@ describe Stretcher::Index do
|
|
21
30
|
def seed_corpus
|
22
31
|
create_tweet_mapping
|
23
32
|
index.bulk_index(corpus)
|
33
|
+
index.refresh
|
24
34
|
end
|
25
35
|
|
26
36
|
it "should work on an existential level" do
|
@@ -63,6 +73,14 @@ describe Stretcher::Index do
|
|
63
73
|
}
|
64
74
|
end
|
65
75
|
|
76
|
+
it "should delete by query" do
|
77
|
+
seed_corpus
|
78
|
+
index.search(:query => {:match_all => {}}).total == 3
|
79
|
+
index.delete_query(:match_all => {})
|
80
|
+
index.refresh
|
81
|
+
index.search(:query => {:match_all => {}}).total == 0
|
82
|
+
end
|
83
|
+
|
66
84
|
it "should search without error" do
|
67
85
|
seed_corpus
|
68
86
|
match_text = corpus.first[:text]
|
@@ -80,7 +98,7 @@ describe Stretcher::Index do
|
|
80
98
|
end
|
81
99
|
|
82
100
|
it "execute the analysis API and return an expected result" do
|
83
|
-
analyzed = index.analyze("Candles", :analyzer => :snowball)
|
101
|
+
analyzed = server.index(:foo).analyze("Candles", :analyzer => :snowball)
|
84
102
|
analyzed.tokens.first.token.should == 'candl'
|
85
103
|
end
|
86
104
|
|
@@ -1,29 +1,38 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Stretcher::
|
3
|
+
describe Stretcher::IndexType do
|
4
4
|
let(:server) { Stretcher::Server.new(ES_URL) }
|
5
|
-
let(:index) {
|
6
|
-
|
5
|
+
let(:index) {
|
6
|
+
i = server.index(:foo)
|
7
|
+
i
|
8
|
+
}
|
9
|
+
let(:type) {
|
10
|
+
t = index.type(:bar)
|
11
|
+
t.delete_query(:match_all => {})
|
12
|
+
index.refresh
|
13
|
+
mapping = {"bar" => {"properties" => {"message" => {"type" => "string"}}}}
|
14
|
+
t.put_mapping mapping
|
15
|
+
t
|
16
|
+
}
|
7
17
|
|
8
18
|
it "should be existentially aware" do
|
9
|
-
|
10
|
-
|
11
|
-
mapping = {"
|
12
|
-
|
13
|
-
|
14
|
-
|
19
|
+
t = index.type(:existential)
|
20
|
+
t.exists?.should be_false
|
21
|
+
mapping = {"existential" => {"properties" => {"message" => {"type" => "string"}}}}
|
22
|
+
t.put_mapping mapping
|
23
|
+
t.exists?.should be_true
|
24
|
+
t.get_mapping.should == mapping
|
15
25
|
end
|
16
26
|
|
17
27
|
describe "searching" do
|
18
28
|
before do
|
19
29
|
@doc = {:message => "hello"}
|
30
|
+
type.put(123123, @doc)
|
31
|
+
index.refresh
|
20
32
|
end
|
21
33
|
|
22
34
|
it "should search and find the right doc" do
|
23
|
-
|
24
|
-
type.put(123123, @doc)
|
25
|
-
index.refresh
|
26
|
-
res = type.search({}, {:query => {:match => {:message => match_text}}})
|
35
|
+
res = type.search({}, {:query => {:match => {:message => @doc[:message]}}})
|
27
36
|
res.results.first.message.should == @doc[:message]
|
28
37
|
end
|
29
38
|
|
@@ -31,21 +40,37 @@ describe Stretcher::Index do
|
|
31
40
|
res = type.search({}, {query: {match_all: {}}, fields: ['message']})
|
32
41
|
res.results.first.message.should == @doc[:message]
|
33
42
|
end
|
43
|
+
|
44
|
+
it "should build results when no document fields are selected" do
|
45
|
+
res = type.search({}, {query: {match_all: {}}, fields: ['_id']})
|
46
|
+
res.results.first.should have_key '_id'
|
47
|
+
end
|
34
48
|
end
|
35
49
|
|
36
|
-
describe "put/get" do
|
50
|
+
describe "put/get/delete" do
|
37
51
|
before do
|
38
52
|
@doc = {:message => "hello!"}
|
53
|
+
@put_res = type.put(987, @doc)
|
39
54
|
end
|
40
55
|
|
41
56
|
it "should put correctly" do
|
42
|
-
|
57
|
+
@put_res.should_not be_nil
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should post correctly" do
|
61
|
+
type.post(@doc).should_not be_nil
|
43
62
|
end
|
44
63
|
|
45
64
|
it "should get individual documents correctly" do
|
46
65
|
type.get(987).message.should == @doc[:message]
|
47
66
|
end
|
48
67
|
|
68
|
+
it "should return nil when retrieving non-extant docs" do
|
69
|
+
lambda {
|
70
|
+
type.get(898323329)
|
71
|
+
}.should raise_exception(Stretcher::RequestError::NotFound)
|
72
|
+
end
|
73
|
+
|
49
74
|
it "should get individual raw documents correctly" do
|
50
75
|
res = type.get(987, true)
|
51
76
|
res["_id"].should == "987"
|
@@ -57,6 +82,12 @@ describe Stretcher::Index do
|
|
57
82
|
type.get(987).message.should == 'Updated!'
|
58
83
|
end
|
59
84
|
|
85
|
+
it "should delete by query correctly" do
|
86
|
+
type.delete_query("match_all" => {})
|
87
|
+
index.refresh
|
88
|
+
type.exists?(987).should be_false
|
89
|
+
end
|
90
|
+
|
60
91
|
it "should delete individual docs correctly" do
|
61
92
|
type.exists?(987).should be_true
|
62
93
|
type.delete(987)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stretcher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-03-
|
12
|
+
date: 2013-03-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: faraday
|