eson-http 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. data/LICENSE.md +20 -0
  2. data/README.md +111 -0
  3. data/Rakefile +31 -0
  4. data/bin/elshell +20 -0
  5. data/eson-http.gemspec +28 -0
  6. data/lib/eson-http.rb +55 -0
  7. data/lib/eson/http.rb +16 -0
  8. data/lib/eson/http/api.rb +13 -0
  9. data/lib/eson/http/client.rb +24 -0
  10. data/lib/eson/http/cluster/health.rb +15 -0
  11. data/lib/eson/http/cluster/nodes.rb +14 -0
  12. data/lib/eson/http/cluster/shutdown.rb +15 -0
  13. data/lib/eson/http/cluster/state.rb +16 -0
  14. data/lib/eson/http/cluster/stats.rb +18 -0
  15. data/lib/eson/http/core/bulk.rb +33 -0
  16. data/lib/eson/http/core/count.rb +26 -0
  17. data/lib/eson/http/core/delete.rb +14 -0
  18. data/lib/eson/http/core/delete_by_query.rb +22 -0
  19. data/lib/eson/http/core/get.rb +15 -0
  20. data/lib/eson/http/core/index.rb +26 -0
  21. data/lib/eson/http/core/mget.rb +23 -0
  22. data/lib/eson/http/core/more_like_this.rb +14 -0
  23. data/lib/eson/http/core/msearch.rb +47 -0
  24. data/lib/eson/http/core/percolate.rb +16 -0
  25. data/lib/eson/http/core/search.rb +29 -0
  26. data/lib/eson/http/core/simple_search.rb +18 -0
  27. data/lib/eson/http/indices/aliases.rb +14 -0
  28. data/lib/eson/http/indices/analyze.rb +14 -0
  29. data/lib/eson/http/indices/clear_cache.rb +18 -0
  30. data/lib/eson/http/indices/close_index.rb +14 -0
  31. data/lib/eson/http/indices/create_index.rb +14 -0
  32. data/lib/eson/http/indices/delete_index.rb +14 -0
  33. data/lib/eson/http/indices/delete_mapping.rb +17 -0
  34. data/lib/eson/http/indices/delete_template.rb +14 -0
  35. data/lib/eson/http/indices/exists.rb +14 -0
  36. data/lib/eson/http/indices/flush.rb +18 -0
  37. data/lib/eson/http/indices/get_mapping.rb +20 -0
  38. data/lib/eson/http/indices/get_settings.rb +18 -0
  39. data/lib/eson/http/indices/get_template.rb +14 -0
  40. data/lib/eson/http/indices/open_index.rb +14 -0
  41. data/lib/eson/http/indices/optimize.rb +18 -0
  42. data/lib/eson/http/indices/put_mapping.rb +16 -0
  43. data/lib/eson/http/indices/put_template.rb +14 -0
  44. data/lib/eson/http/indices/refresh.rb +18 -0
  45. data/lib/eson/http/indices/segments.rb +18 -0
  46. data/lib/eson/http/indices/snapshot.rb +18 -0
  47. data/lib/eson/http/indices/stats.rb +18 -0
  48. data/lib/eson/http/indices/status.rb +18 -0
  49. data/lib/eson/http/indices/update_settings.rb +18 -0
  50. data/lib/eson/http/request.rb +95 -0
  51. data/lib/eson/modules/response_parser.rb +22 -0
  52. data/lib/eson/modules/status_handler.rb +24 -0
  53. data/log4j.properties +18 -0
  54. data/test/http/client_test.rb +14 -0
  55. data/test/http/cluster_test.rb +58 -0
  56. data/test/http/index_test.rb +180 -0
  57. data/test/http/indices/basics_test.rb +257 -0
  58. data/test/http/query_test.rb +70 -0
  59. data/test/modules/query_plugin_test.rb +40 -0
  60. data/test/seeds/seeds.rb +30 -0
  61. data/test/test_config.rb +33 -0
  62. metadata +202 -0
data/LICENSE.md ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Florian Gilcher <florian.gilcher@asquera.de>, Felix Gilcher <felix.gilcher@asquera.de>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,111 @@
1
+ # eson-http. A HTTP client for elasticsearch
2
+
3
+ Eson provides a fairly complete implementation of the elasticsearch HTTPAPI for ruby.
4
+
5
+ It tries to keep the language of the ES API as intact as possible.
6
+
7
+ ## Usage
8
+
9
+ require 'eson-http'
10
+
11
+ c = Eson::HTTP::Client.new(:server => 'http://localhost:9200')
12
+
13
+ doc = {
14
+ :user => "kimchy",
15
+ :post_date => "2009-11-15T14:12:12",
16
+ :message => "trying out Elastic Search"
17
+ }
18
+
19
+ c.index :index => "twitter",
20
+ :type => "tweet",
21
+ :id => 1,
22
+ :document => doc
23
+
24
+ c.get :type => "tweet", :id => 1 # returns the document
25
+
26
+ c.search :q => "message:trying"
27
+
28
+ c.count :q => "*"
29
+
30
+ ## Building requests by hand
31
+
32
+ The client has an additional mode that does not call elasticsearch immediately, but returns the request object instead.
33
+
34
+ require 'echolon/http'
35
+
36
+ c = Eson::HTTP::Client.new(:server => 'http://localhost:9200',
37
+ :auto_call => false)
38
+
39
+ doc = {
40
+ :user => "kimchy",
41
+ :post_date => "2009-11-15T14:12:12",
42
+ :message => "trying out Elastic Search"
43
+ }
44
+
45
+ index_request = c.index
46
+ index_request.index = "twitter"
47
+ index_request.type = "tweet"
48
+ index_request.id = 1
49
+ index_request.doc = doc
50
+
51
+ index_request.call
52
+
53
+ # or:
54
+
55
+ index_request = c.index
56
+ index_request.params = {
57
+ :index => "twitter",
58
+ :type => "tweet"
59
+ :id => 1,
60
+ :doc => doc
61
+ }
62
+
63
+ # or:
64
+
65
+ index_request = c.index :index => "twitter",
66
+ :type => "tweet"
67
+ :id => 1,
68
+ :doc => doc
69
+
70
+ ## Bulk Requests
71
+
72
+ `bulk` and `msearch` requests can be constructed by calling the respective client methods on them:
73
+
74
+
75
+ ```
76
+ c.bulk do |b|
77
+ b.index :index => "default",
78
+ :type => "bar"
79
+ :doc => {"foo" => "bar"}
80
+ b.delete :index => "default",
81
+ :id => '134'
82
+ end
83
+
84
+ c.msearch do |s|
85
+ s.search #....
86
+ end
87
+ ```
88
+
89
+ ## The shell
90
+
91
+ Eson-HTTP comes with a quick-and-dirty shell, if you have pry installed:
92
+
93
+ $ elshell 127.0.0.1:9200
94
+ pry(#<ElasticSearch::Client:0x000001014f4078>)> node
95
+ => "127.0.0.1:9200"
96
+
97
+ pry(#<ElasticSearch::Client:0x000001014f4078>)> index_name
98
+ => "twitter"
99
+
100
+ pry(#<ElasticSearch::Client:0x000001014f4078>)> get :type => 'tweet', :id => 2
101
+ => {"_index"=>"twitter", "_type"=>"tweet", "_id"=>"2", "_version"=>1, "_source"=>{"user"=>"kimchy", "post_date"=>"2009-11-15T14:12:12", "message"=>"You know, for Search"}}
102
+
103
+
104
+ ## TODO
105
+
106
+ * Test suite needs to be reordered. Its the oldest part of the project and a bit messy.
107
+ * Filters in aliases are not supported
108
+
109
+ ## See also
110
+
111
+ * Tire
data/Rakefile ADDED
@@ -0,0 +1,31 @@
1
+ require 'rake/testtask'
2
+ require 'rake/gempackagetask'
3
+ require 'rake/testtask'
4
+
5
+ def gemspec
6
+ @gemspec ||= begin
7
+ file = File.expand_path("eson-http.gemspec")
8
+ ::Gem::Specification.load(file)
9
+ end
10
+ end
11
+
12
+ desc "Validates the gemspec"
13
+ task :gemspec do
14
+ gemspec.validate
15
+ end
16
+
17
+ Rake::GemPackageTask.new(gemspec) do |pkg|
18
+ pkg.gem_spec = gemspec
19
+ end
20
+
21
+ task :package => :gemspec
22
+
23
+ Rake::TestTask.new(:test) do |test|
24
+ test.pattern = 'test/**/*_test.rb'
25
+
26
+ test.verbose = true
27
+ end
28
+
29
+ task :seed do
30
+ require './test/seeds/seeds'
31
+ end
data/bin/elshell ADDED
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH << File.join(File.dirname(File.dirname(__FILE__)), "lib")
4
+
5
+ require 'echolon-http'
6
+ require 'echolon-search'
7
+
8
+ require 'elsearch-node'
9
+
10
+ require 'node/external'
11
+
12
+ require 'rest-client'
13
+ require 'addressable/template'
14
+
15
+ require 'pry'
16
+
17
+ c = Eson::HTTP::Client.new(:server => ARGV.first || 'http://localhost:9200',
18
+ :logger => Logger.new($stdout))
19
+
20
+ c.pry
data/eson-http.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ #require "./lib/elsearch"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "eson-http"
7
+ s.version = "0.7.0" #Echolon::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Florian Gilcher"]
10
+ s.email = ["florian.gilcher@asquera.de"]
11
+ s.homepage = ""
12
+ s.summary = %q{A modular client for Eson - HTTP interface}
13
+ s.description = %q{A modular client for Eson. It provides
14
+ an implementation of the Query language as well as multiple client implementations
15
+ for HTTP and native access.}
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ #s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ #s.add_dependency "typhoeus"
23
+ s.add_dependency "faraday", "~> 0.7.0"
24
+ s.add_dependency "addressable"
25
+ s.add_dependency "eson-core"
26
+ s.add_development_dependency "elasticsearch-node"
27
+ s.add_development_dependency "riot"
28
+ end
data/lib/eson-http.rb ADDED
@@ -0,0 +1,55 @@
1
+ require 'eson-core'
2
+
3
+ require 'addressable/template'
4
+
5
+ require 'eson/http'
6
+
7
+ require 'eson/modules/status_handler'
8
+ require 'eson/modules/response_parser'
9
+
10
+ require 'eson/http/client'
11
+ require 'eson/http/request'
12
+ require 'eson/http/api'
13
+
14
+ require 'eson/http/core/index'
15
+ require 'eson/http/core/get'
16
+ require 'eson/http/core/delete'
17
+ require 'eson/http/core/search'
18
+ require 'eson/http/core/delete_by_query'
19
+ require 'eson/http/core/count'
20
+ require 'eson/http/core/bulk'
21
+ require 'eson/http/core/percolate'
22
+ require 'eson/http/core/simple_search'
23
+ require 'eson/http/core/more_like_this'
24
+ require 'eson/http/core/msearch'
25
+ require 'eson/http/core/mget'
26
+
27
+ require 'eson/http/cluster/health'
28
+ require 'eson/http/cluster/state'
29
+ require 'eson/http/cluster/nodes'
30
+ require 'eson/http/cluster/stats'
31
+ require 'eson/http/cluster/shutdown'
32
+
33
+ require 'eson/http/indices/aliases'
34
+ require 'eson/http/indices/analyze'
35
+ require 'eson/http/indices/clear_cache'
36
+ require 'eson/http/indices/close_index'
37
+ require 'eson/http/indices/create_index'
38
+ require 'eson/http/indices/delete_index'
39
+ require 'eson/http/indices/delete_mapping'
40
+ require 'eson/http/indices/flush'
41
+ require 'eson/http/indices/get_mapping'
42
+ require 'eson/http/indices/get_settings'
43
+ require 'eson/http/indices/open_index'
44
+ require 'eson/http/indices/optimize'
45
+ require 'eson/http/indices/put_mapping'
46
+ require 'eson/http/indices/refresh'
47
+ require 'eson/http/indices/snapshot'
48
+ require 'eson/http/indices/status'
49
+ require 'eson/http/indices/put_template'
50
+ require 'eson/http/indices/get_template'
51
+ require 'eson/http/indices/delete_template'
52
+ require 'eson/http/indices/update_settings'
53
+ require 'eson/http/indices/exists'
54
+ require 'eson/http/indices/stats'
55
+ require 'eson/http/indices/segments'
data/lib/eson/http.rb ADDED
@@ -0,0 +1,16 @@
1
+ module Eson
2
+ module HTTP
3
+ def self.logger=(logger)
4
+ if String === logger
5
+ require 'logger'
6
+ @logger = Logger.new(logger)
7
+ else
8
+ @logger = logger
9
+ end
10
+ end
11
+
12
+ def self.logger
13
+ @logger
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,13 @@
1
+ module Eson
2
+ module HTTP
3
+ module API
4
+ include Eson::API
5
+
6
+ def request_method(method)
7
+ define_method :request_method do
8
+ @request_method || method
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,24 @@
1
+ module Eson
2
+ module HTTP
3
+ class Client < Eson::Client
4
+ DEFAULT_OPTS = {
5
+ :server => "http://localhost:9200",
6
+ :protocol => Eson::HTTP
7
+ }
8
+
9
+ def initialize(opts = {})
10
+ opts = DEFAULT_OPTS.merge(:plugins => default_plugins).merge(opts)
11
+ super(opts)
12
+ end
13
+
14
+ private
15
+ def default_plugins
16
+ [Eson::StatusHandler, Eson::ResponseParser].tap do |plugins|
17
+ if defined? Eson::QueryPlugin
18
+ plugins.unshift(Eson::QueryPlugin)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,15 @@
1
+ module Eson
2
+ module HTTP
3
+ module Health
4
+ include Shared::Health
5
+ extend API
6
+
7
+ request_method :get
8
+
9
+ def path
10
+ '/_cluster/health/{-list|,|indices}'
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ module Eson
2
+ module HTTP
3
+ module Nodes
4
+ include Shared::Nodes
5
+ extend API
6
+
7
+ request_method :get
8
+
9
+ def path
10
+ '/_cluster/nodes/{-list|,|nodes}'
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,15 @@
1
+ module Eson
2
+ module HTTP
3
+ module Shutdown
4
+ #TODO fully implement and test this
5
+ include Shared::Shutdown
6
+ extend API
7
+
8
+ request_method :post
9
+
10
+ def path
11
+ '/_cluster/nodes/{-list|,|nodes}/_shutdown'
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ module Eson
2
+ module HTTP
3
+ module State
4
+ include Shared::State
5
+ extend API
6
+ #TODO implement filter_indices correctly
7
+
8
+ request_method :get
9
+
10
+ def path
11
+ '/_cluster/state'
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ module Eson
2
+ module HTTP
3
+ module Stats
4
+ include Shared::Stats
5
+ extend API
6
+
7
+ request_method :get
8
+
9
+ def path
10
+ if nodes.empty?
11
+ '/_cluster/nodes/stats'
12
+ else
13
+ '/_cluster/nodes/{-list|,|nodes}/stats'
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,33 @@
1
+ module Eson
2
+ module HTTP
3
+ module Bulk
4
+ include Shared::Bulk
5
+ extend API
6
+
7
+ request_method :put
8
+
9
+ def path
10
+ '/_bulk'
11
+ end
12
+
13
+ def source
14
+ bulk.map {|r| serialize_request(r)}.join
15
+ end
16
+
17
+ def serialize_request(request)
18
+ case request
19
+ when Eson::HTTP::Index
20
+ MultiJson.encode({ "index" => to_params_hash(request) }) << "\n" << request.source << "\n"
21
+ when Eson::HTTP::Delete
22
+ MultiJson.encode({ "delete" => to_params_hash(request) }) << "\n"
23
+ else
24
+ warn("Unserializable request #{request.inspect}")
25
+ end
26
+ end
27
+
28
+ def to_params_hash(r)
29
+ { "_index" => r.index, "_type" => r.type, "_id" => r.id }
30
+ end
31
+ end
32
+ end
33
+ end