rubberband 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +5 -5
- data/Rakefile +1 -1
- data/TODO +8 -28
- data/lib/elasticsearch/client/index.rb +26 -6
- data/lib/elasticsearch/transport.rb +1 -0
- data/lib/elasticsearch/transport/base_protocol.rb +9 -1
- data/lib/elasticsearch/transport/http.rb +1 -1
- data/lib/elasticsearch/transport/memcached.rb +72 -0
- data/lib/elasticsearch/transport/thrift.rb +1 -1
- data/lib/elasticsearch/version.rb +1 -1
- data/rubberband.gemspec +6 -3
- data/test/type_test.rb +44 -0
- metadata +7 -4
data/README.rdoc
CHANGED
@@ -9,8 +9,9 @@ Copyright 2010 Grant Rodgers. See included LICENSE file.
|
|
9
9
|
|
10
10
|
== Features
|
11
11
|
|
12
|
-
* Automatic failover and
|
13
|
-
* Multiple transports
|
12
|
+
* Automatic failover, retry, and peer discovery
|
13
|
+
* Multiple transports (HTTP, Thrift, Memcached TODO)
|
14
|
+
* Multiple encodings (JSON (Yajl), Smile TODO)
|
14
15
|
|
15
16
|
== Usage
|
16
17
|
|
@@ -18,7 +19,7 @@ Instantiate a client:
|
|
18
19
|
|
19
20
|
client = ElasticSearch.new('127.0.0.1:9200', :index => "twitter", :type => "tweet")
|
20
21
|
|
21
|
-
API
|
22
|
+
API:
|
22
23
|
|
23
24
|
client.index({:body => "elasticsearch is cool"}, :id => 1)
|
24
25
|
client.get("1")
|
@@ -26,8 +27,7 @@ API is subject to change, but here is a trivial example:
|
|
26
27
|
|
27
28
|
== TODO
|
28
29
|
|
29
|
-
|
30
|
-
|
30
|
+
See TODO file.
|
31
31
|
|
32
32
|
== Contributing
|
33
33
|
|
data/Rakefile
CHANGED
data/TODO
CHANGED
@@ -1,29 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
search*
|
8
|
-
terms
|
9
|
-
more_like_this
|
10
|
-
admin index api:
|
11
|
-
status*
|
12
|
-
create*
|
13
|
-
delete*
|
14
|
-
alias*
|
15
|
-
mapping*
|
16
|
-
flush*
|
17
|
-
refresh*
|
18
|
-
snapshot*
|
19
|
-
optimize*
|
20
|
-
admin cluster api:
|
21
|
-
health*
|
22
|
-
state*
|
23
|
-
nodes info*
|
24
|
-
nodes stats*
|
25
|
-
nodes shutdown*
|
26
|
-
nodes restart*
|
27
|
-
|
28
|
-
handle partial failure cases where some shards are unsuccessful (maybe raise a PartialResult exception, allow override option to return results anyway. results should have a flag that signifies incompleteness)
|
1
|
+
delete_by_query
|
2
|
+
terms
|
3
|
+
more_like_this
|
4
|
+
bulk ops
|
5
|
+
test scroll better, maybe add a scroller object
|
6
|
+
handle partial failure cases where some shards are unsuccessful (optionally raise a PartialResult exception, allow override option to return results anyway. results should have a flag that signifies incompleteness)
|
29
7
|
tests/specs/features
|
8
|
+
memcached transport
|
9
|
+
smile encoding
|
@@ -13,11 +13,16 @@ module ElasticSearch
|
|
13
13
|
# timeout (optional)
|
14
14
|
# document (optional)
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
if @batch
|
17
|
+
@batch << { :index => { :_index => options[:index], :_type => options[:type], :_id => options[:id] }}
|
18
|
+
@batch << document
|
19
19
|
else
|
20
|
-
|
20
|
+
result = execute(:index, options[:index], options[:type], options[:id], document, options)
|
21
|
+
if result["ok"]
|
22
|
+
result["_id"]
|
23
|
+
else
|
24
|
+
false
|
25
|
+
end
|
21
26
|
end
|
22
27
|
end
|
23
28
|
|
@@ -38,8 +43,13 @@ module ElasticSearch
|
|
38
43
|
def delete(id, options={})
|
39
44
|
set_default_scope!(options)
|
40
45
|
raise "index and type or defaults required" unless options[:index] && options[:type]
|
41
|
-
|
42
|
-
|
46
|
+
|
47
|
+
if @batch
|
48
|
+
@batch << { :delete => { :_index => options[:index], :_type => options[:type], :_id => id }}
|
49
|
+
else
|
50
|
+
result = execute(:delete, options[:index], options[:type], id, options)
|
51
|
+
result["ok"]
|
52
|
+
end
|
43
53
|
end
|
44
54
|
|
45
55
|
#df The default field to use when no field prefix is defined within the query.
|
@@ -89,6 +99,16 @@ module ElasticSearch
|
|
89
99
|
response["count"].to_i #TODO check if count is nil
|
90
100
|
end
|
91
101
|
|
102
|
+
# Starts a bulk operation batch and yields self. Index and delete requests will be
|
103
|
+
# queued until the block closes, then sent as a single _bulk call.
|
104
|
+
def bulk
|
105
|
+
@batch = []
|
106
|
+
yield(self)
|
107
|
+
response = execute(:bulk, @batch)
|
108
|
+
ensure
|
109
|
+
@batch = nil
|
110
|
+
end
|
111
|
+
|
92
112
|
private
|
93
113
|
|
94
114
|
def slice_hash(hash, *keys)
|
@@ -68,6 +68,13 @@ module ElasticSearch
|
|
68
68
|
handle_error(response) unless response.status == 200
|
69
69
|
encoder.decode(response.body) # {"count", "_shards"=>{"failed", "total", "successful"}}
|
70
70
|
end
|
71
|
+
|
72
|
+
def bulk(actions)
|
73
|
+
body = actions.inject("") { |a, s| a << encoder.encode(s) << "\n" }
|
74
|
+
response = request(:post, {:op => '_bulk'}, {}, body)
|
75
|
+
handle_error(response) unless response.status == 200
|
76
|
+
encoder.decode(response.body) # {"items => [ {"delete"/"create" => {"_index", "_type", "_id", "ok"}} ] }
|
77
|
+
end
|
71
78
|
end
|
72
79
|
|
73
80
|
module IndexAdminProtocol
|
@@ -154,8 +161,9 @@ module ElasticSearch
|
|
154
161
|
def generate_uri(options)
|
155
162
|
path = ""
|
156
163
|
path << "/#{Array(options[:index]).collect { |i| escape(i.downcase) }.join(",")}" if options[:index] && !options[:index].empty?
|
164
|
+
path << "/" if options[:index] && options[:index].empty?
|
157
165
|
path << "/#{Array(options[:type]).collect { |t| escape(t) }.join(",")}" if options[:type] && !options[:type].empty?
|
158
|
-
path << "/#{Array(options[:id]).collect { |id| escape(id) }.join(",")}" if options[:id] && !options[:id].empty?
|
166
|
+
path << "/#{Array(options[:id]).collect { |id| escape(id) }.join(",")}" if options[:id] && !options[:id].to_s.empty?
|
159
167
|
path << "/#{options[:op]}" if options[:op]
|
160
168
|
path
|
161
169
|
end
|
@@ -38,7 +38,7 @@ module ElasticSearch
|
|
38
38
|
uri = generate_uri(operation)
|
39
39
|
query = generate_query_string(params)
|
40
40
|
path = [uri, query].join("?")
|
41
|
-
#puts "request: #{@server} #{path} #{body}"
|
41
|
+
#puts "request: #{method} #{@server} #{path} #{body}"
|
42
42
|
response = @session.request(method, path, headers, :data => body)
|
43
43
|
handle_error(response) if response.status >= 500
|
44
44
|
response
|
@@ -0,0 +1,72 @@
|
|
1
|
+
begin
|
2
|
+
require 'memcached'
|
3
|
+
rescue LoadError => error
|
4
|
+
raise "Please install the memcached gem to use the memcached transport."
|
5
|
+
end
|
6
|
+
|
7
|
+
module ElasticSearch
|
8
|
+
module Transport
|
9
|
+
class Memcached < Base
|
10
|
+
Response = Struct.new(:status, :headers, :body)
|
11
|
+
|
12
|
+
DEFAULTS = {
|
13
|
+
:timeout => 5
|
14
|
+
}.freeze
|
15
|
+
|
16
|
+
def initialize(server, options={})
|
17
|
+
super
|
18
|
+
@options = DEFAULTS.merge(@options)
|
19
|
+
end
|
20
|
+
|
21
|
+
def connect!
|
22
|
+
@memcached = ::Memcached.new(@server, :timeout => @options[:timeout]) #TODO allow passing other options?
|
23
|
+
end
|
24
|
+
|
25
|
+
def close
|
26
|
+
@memcached.quit
|
27
|
+
end
|
28
|
+
|
29
|
+
def all_nodes
|
30
|
+
memcached_addresses = nodes_info([])["nodes"].collect { |id, node| node["memcached_address"] }
|
31
|
+
memcached_addresses.collect! do |a|
|
32
|
+
if a =~ /inet\[.*\/([\d.:]+)\]/
|
33
|
+
$1
|
34
|
+
end
|
35
|
+
end.compact!
|
36
|
+
memcached_addresses
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def request(method, operation, params={}, body=nil, headers={})
|
42
|
+
begin
|
43
|
+
uri = generate_uri(operation)
|
44
|
+
query = generate_query_string(params)
|
45
|
+
path = [uri, query].join("?")
|
46
|
+
#puts "request: #{method} #{@server} #{path} #{body}"
|
47
|
+
response = case method
|
48
|
+
when :get
|
49
|
+
@memcached.get(path, false)
|
50
|
+
when :put, :post
|
51
|
+
#TODO put vs post?
|
52
|
+
@memcached.set(path, body, 0, false)
|
53
|
+
when :delete
|
54
|
+
@memcached.delete(path)
|
55
|
+
end
|
56
|
+
#puts "response: #{response}"
|
57
|
+
response = Response.new(200, {}, response) #TODO
|
58
|
+
handle_error(response) if response.status >= 500
|
59
|
+
response
|
60
|
+
rescue Exception => e
|
61
|
+
case e
|
62
|
+
when TimeoutError
|
63
|
+
raise TimeoutError
|
64
|
+
else
|
65
|
+
raise e
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -76,7 +76,7 @@ module ElasticSearch
|
|
76
76
|
when :get
|
77
77
|
request.method = ElasticSearch::Thrift::Method::GET
|
78
78
|
when :put
|
79
|
-
request.method = ElasticSearch::Thrift::Method::
|
79
|
+
request.method = ElasticSearch::Thrift::Method::PUT
|
80
80
|
when :post
|
81
81
|
request.method = ElasticSearch::Thrift::Method::POST
|
82
82
|
when :delete
|
data/rubberband.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{rubberband}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.6"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["grantr"]
|
12
|
-
s.date = %q{
|
12
|
+
s.date = %q{2011-01-07}
|
13
13
|
s.description = %q{An ElasticSearch client with ThriftClient-like failover handling.}
|
14
14
|
s.email = %q{grantr@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -41,6 +41,7 @@ Gem::Specification.new do |s|
|
|
41
41
|
"lib/elasticsearch/transport/base.rb",
|
42
42
|
"lib/elasticsearch/transport/base_protocol.rb",
|
43
43
|
"lib/elasticsearch/transport/http.rb",
|
44
|
+
"lib/elasticsearch/transport/memcached.rb",
|
44
45
|
"lib/elasticsearch/transport/thrift.rb",
|
45
46
|
"lib/elasticsearch/transport/thrift/elasticsearch_constants.rb",
|
46
47
|
"lib/elasticsearch/transport/thrift/elasticsearch_types.rb",
|
@@ -51,6 +52,7 @@ Gem::Specification.new do |s|
|
|
51
52
|
"test/elasticsearch_test.rb",
|
52
53
|
"test/hits_test.rb",
|
53
54
|
"test/test_helper.rb",
|
55
|
+
"test/type_test.rb",
|
54
56
|
"vendor/elasticsearch/elasticsearch.thrift"
|
55
57
|
]
|
56
58
|
s.homepage = %q{http://github.com/grantr/rubberband}
|
@@ -61,7 +63,8 @@ Gem::Specification.new do |s|
|
|
61
63
|
s.test_files = [
|
62
64
|
"test/elasticsearch_test.rb",
|
63
65
|
"test/hits_test.rb",
|
64
|
-
"test/test_helper.rb"
|
66
|
+
"test/test_helper.rb",
|
67
|
+
"test/type_test.rb"
|
65
68
|
]
|
66
69
|
|
67
70
|
if s.respond_to? :specification_version then
|
data/test/type_test.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TypeTest < Test::Unit::TestCase
|
4
|
+
context "Test with differents Types" do
|
5
|
+
#TODO figure out how to have one setup and one teardown
|
6
|
+
setup do
|
7
|
+
@client = ElasticSearch.new('127.0.0.1:9200', :index => "twitter", :type => "tweet")
|
8
|
+
@client.index({:user => "kimchy"}, :id => 1)
|
9
|
+
@client.index({:user => "kimchy"}, :id => 2, :type => "grillo")
|
10
|
+
@client.index({:user => "kimchy"}, :id => 3, :type => "cote")
|
11
|
+
@client.index({:user => "kimchy"}, :id => 4, :index => "cotes", :type => "cote")
|
12
|
+
@client.index({:user => "kimchy"}, :id => 5, :index => "menchos", :type => "mencho")
|
13
|
+
@client.index({:user => "kimchy"}, :id => 6, :index => "menchos", :type => "cote")
|
14
|
+
@client.refresh("twitter", "cotes", "menchos")
|
15
|
+
end
|
16
|
+
|
17
|
+
teardown do
|
18
|
+
#@client.delete_index("twitter")
|
19
|
+
#@client.delete_index("cotes")
|
20
|
+
#@client.delete_index("menchos")
|
21
|
+
end
|
22
|
+
|
23
|
+
should "search in all indexes" do
|
24
|
+
assert_equal @client.count("kimchy",{:index => "", :type => ""}), 6
|
25
|
+
end
|
26
|
+
|
27
|
+
should "search in all types with index twitter" do
|
28
|
+
assert_equal @client.count("kimchy",{:index => "twitter", :type => ""}), 3
|
29
|
+
end
|
30
|
+
|
31
|
+
should "search in index twitter with types tweet,cote" do
|
32
|
+
assert_equal @client.count("kimchy",{:index => "twitter", :type => "tweet,cote"}), 2
|
33
|
+
end
|
34
|
+
|
35
|
+
should "search in index twitter,cotes" do
|
36
|
+
assert_equal @client.count("kimchy",{:index => "twitter,cotes", :type => ""}), 4
|
37
|
+
end
|
38
|
+
|
39
|
+
should "search in types grillo,cote of all indexes" do
|
40
|
+
assert_equal @client.count("kimchy",{:index => "", :type => "grillo,cote"}), 4
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 6
|
9
|
+
version: 0.0.6
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- grantr
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date:
|
17
|
+
date: 2011-01-07 00:00:00 -08:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -133,6 +133,7 @@ files:
|
|
133
133
|
- lib/elasticsearch/transport/base.rb
|
134
134
|
- lib/elasticsearch/transport/base_protocol.rb
|
135
135
|
- lib/elasticsearch/transport/http.rb
|
136
|
+
- lib/elasticsearch/transport/memcached.rb
|
136
137
|
- lib/elasticsearch/transport/thrift.rb
|
137
138
|
- lib/elasticsearch/transport/thrift/elasticsearch_constants.rb
|
138
139
|
- lib/elasticsearch/transport/thrift/elasticsearch_types.rb
|
@@ -143,6 +144,7 @@ files:
|
|
143
144
|
- test/elasticsearch_test.rb
|
144
145
|
- test/hits_test.rb
|
145
146
|
- test/test_helper.rb
|
147
|
+
- test/type_test.rb
|
146
148
|
- vendor/elasticsearch/elasticsearch.thrift
|
147
149
|
has_rdoc: true
|
148
150
|
homepage: http://github.com/grantr/rubberband
|
@@ -158,7 +160,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
158
160
|
requirements:
|
159
161
|
- - ">="
|
160
162
|
- !ruby/object:Gem::Version
|
161
|
-
hash: -
|
163
|
+
hash: -3014120754088484755
|
162
164
|
segments:
|
163
165
|
- 0
|
164
166
|
version: "0"
|
@@ -181,3 +183,4 @@ test_files:
|
|
181
183
|
- test/elasticsearch_test.rb
|
182
184
|
- test/hits_test.rb
|
183
185
|
- test/test_helper.rb
|
186
|
+
- test/type_test.rb
|