esearch 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. data/.gitignore +5 -0
  2. data/.rspec +6 -0
  3. data/.travis.yml +19 -0
  4. data/Changelog.md +27 -0
  5. data/Gemfile +6 -0
  6. data/Gemfile.devtools +60 -0
  7. data/Guardfile +18 -0
  8. data/LICENSE +20 -0
  9. data/README.md +93 -0
  10. data/Rakefile +2 -0
  11. data/TODO +3 -0
  12. data/config/devtools.yml +2 -0
  13. data/config/flay.yml +3 -0
  14. data/config/flog.yml +3 -0
  15. data/config/mutant.yml +3 -0
  16. data/config/reek.yml +103 -0
  17. data/config/yardstick.yml +2 -0
  18. data/esearch.gemspec +26 -0
  19. data/lib/esearch.rb +43 -0
  20. data/lib/esearch/cluster.rb +85 -0
  21. data/lib/esearch/command.rb +158 -0
  22. data/lib/esearch/command/cluster.rb +28 -0
  23. data/lib/esearch/command/document.rb +111 -0
  24. data/lib/esearch/command/exist.rb +37 -0
  25. data/lib/esearch/command/index.rb +66 -0
  26. data/lib/esearch/command/search.rb +24 -0
  27. data/lib/esearch/command/status.rb +24 -0
  28. data/lib/esearch/connection.rb +36 -0
  29. data/lib/esearch/document.rb +53 -0
  30. data/lib/esearch/index.rb +61 -0
  31. data/lib/esearch/indices.rb +52 -0
  32. data/lib/esearch/mixin.rb +111 -0
  33. data/lib/esearch/presenter.rb +43 -0
  34. data/lib/esearch/presenter/aspect.rb +17 -0
  35. data/lib/esearch/presenter/aspect/range.rb +63 -0
  36. data/lib/esearch/presenter/aspect/term.rb +19 -0
  37. data/lib/esearch/presenter/cluster.rb +84 -0
  38. data/lib/esearch/presenter/document.rb +102 -0
  39. data/lib/esearch/presenter/facet.rb +72 -0
  40. data/lib/esearch/presenter/hit.rb +70 -0
  41. data/lib/esearch/presenter/hits.rb +60 -0
  42. data/lib/esearch/presenter/index.rb +23 -0
  43. data/lib/esearch/presenter/search.rb +32 -0
  44. data/lib/esearch/presenter/status.rb +18 -0
  45. data/lib/esearch/request.rb +90 -0
  46. data/lib/esearch/type.rb +40 -0
  47. data/spec/integration/esearch/spike_spec.rb +50 -0
  48. data/spec/spec_helper.rb +65 -0
  49. data/spec/support/example_group_methods.rb +7 -0
  50. data/spec/support/ice_nine_config.rb +6 -0
  51. data/spec/unit/esearch/cluster/class_methods/connect_spec.rb +16 -0
  52. data/spec/unit/esearch/cluster/health_spec.rb +10 -0
  53. data/spec/unit/esearch/cluster/index_spec.rb +11 -0
  54. data/spec/unit/esearch/cluster/indices_spec.rb +11 -0
  55. data/spec/unit/esearch/cluster/path_spec.rb +11 -0
  56. data/spec/unit/esearch/command/class_methods/run_spec.rb +16 -0
  57. data/spec/unit/esearch/command/cluster/health/run_spec.rb +14 -0
  58. data/spec/unit/esearch/command/document/delete/run_spec.rb +13 -0
  59. data/spec/unit/esearch/command/document/get/result_spec.rb +27 -0
  60. data/spec/unit/esearch/command/document/index/create/run_spec.rb +17 -0
  61. data/spec/unit/esearch/command/document/index/run_create_spec.rb +17 -0
  62. data/spec/unit/esearch/command/document/index/run_spec.rb +15 -0
  63. data/spec/unit/esearch/command/document/index/run_update_spec.rb +15 -0
  64. data/spec/unit/esearch/command/document/index/update/run_spec.rb +15 -0
  65. data/spec/unit/esearch/command/exist/result_spec.rb +39 -0
  66. data/spec/unit/esearch/command/index/create/run_spec.rb +14 -0
  67. data/spec/unit/esearch/command/index/delete/run_spec.rb +13 -0
  68. data/spec/unit/esearch/command/index/refresh/run_spec.rb +13 -0
  69. data/spec/unit/esearch/command/result_spec.rb +68 -0
  70. data/spec/unit/esearch/command/search/run_spec.rb +14 -0
  71. data/spec/unit/esearch/command/status/run_spec.rb +13 -0
  72. data/spec/unit/esearch/connection/class_methods/build_spec.rb +29 -0
  73. data/spec/unit/esearch/connection/run_spec.rb +36 -0
  74. data/spec/unit/esearch/document/connection_spec.rb +12 -0
  75. data/spec/unit/esearch/document/delete_spec.rb +12 -0
  76. data/spec/unit/esearch/document/get_spec.rb +12 -0
  77. data/spec/unit/esearch/index/create_spec.rb +12 -0
  78. data/spec/unit/esearch/index/delete_spec.rb +11 -0
  79. data/spec/unit/esearch/index/type_spec.rb +12 -0
  80. data/spec/unit/esearch/indices/all/path_spec.rb +12 -0
  81. data/spec/unit/esearch/mixin/document/index_create_spec.rb +31 -0
  82. data/spec/unit/esearch/mixin/document/index_spec.rb +31 -0
  83. data/spec/unit/esearch/mixin/document/index_update_spec.rb +31 -0
  84. data/spec/unit/esearch/mixin/exist/exist_predicate_spec.rb +16 -0
  85. data/spec/unit/esearch/mixin/index/refresh_spec.rb +16 -0
  86. data/spec/unit/esearch/mixin/index/status_spec.rb +16 -0
  87. data/spec/unit/esearch/mixin/search/search_spec.rb +18 -0
  88. data/spec/unit/esearch/presenter/aspect/range/from_spec.rb +24 -0
  89. data/spec/unit/esearch/presenter/aspect/range/to_spec.rb +24 -0
  90. data/spec/unit/esearch/presenter/class_methods/new_spec.rb +37 -0
  91. data/spec/unit/esearch/presenter/facet/build_spec.rb +26 -0
  92. data/spec/unit/esearch/presenter/facet/class_methods/build_spec.rb +26 -0
  93. data/spec/unit/esearch/presenter/hit/fields_spec.rb +24 -0
  94. data/spec/unit/esearch/presenter/hit/source_spec.rb +24 -0
  95. data/spec/unit/esearch/presenter/hits/each_spec.rb +15 -0
  96. data/spec/unit/esearch/presenter/hits/size_spec.rb +13 -0
  97. data/spec/unit/esearch/request/initialize_spec.rb +39 -0
  98. data/spec/unit/esearch/request/run_spec.rb +39 -0
  99. data/spec/unit/esearch/type/connection_spec.rb +15 -0
  100. data/spec/unit/esearch/type/document_spec.rb +12 -0
  101. metadata +330 -0
@@ -0,0 +1,85 @@
1
+ module Esearch
2
+ # Handle for an elasticsearch cluster
3
+ class Cluster
4
+
5
+ include Adamantium::Flat, Concord.new(:connection)
6
+
7
+ # Return connection
8
+ #
9
+ # @return [Connection]
10
+ #
11
+ # @api private
12
+ #
13
+ attr_reader :connection
14
+
15
+ # Return handler for index
16
+ #
17
+ # @param [String] name
18
+ #
19
+ # @return [Index]
20
+ #
21
+ # @api private
22
+ #
23
+ def index(name)
24
+ Index.new(connection, name)
25
+ end
26
+
27
+ # Return handler for indices
28
+ #
29
+ # @param [Enumerable<String>] names
30
+ #
31
+ # @return [Indices]
32
+ #
33
+ # @api private
34
+ #
35
+ def indices(names)
36
+ Indices.new(connection, names)
37
+ end
38
+
39
+ # Return cluster health
40
+ #
41
+ # @param [Hash] options
42
+ #
43
+ # @return [Presenter::Health]
44
+ #
45
+ # @api private
46
+ #
47
+ def health(options = {})
48
+ Command::Cluster::Health.run(self, options)
49
+ end
50
+
51
+ # Return path
52
+ #
53
+ # @return [Pathname]
54
+ #
55
+ # @api private
56
+ #
57
+ def path
58
+ self.class::PATH
59
+ end
60
+
61
+ PATH = Pathname.new('/')
62
+
63
+ # Return handler for all indices
64
+ #
65
+ # @return [Indices::All]
66
+ #
67
+ # @api private
68
+ #
69
+ def all_indices
70
+ Indices::All.new(connection)
71
+ end
72
+ memoize :all_indices
73
+
74
+ # Build connection
75
+ #
76
+ # @return [Connection]
77
+ #
78
+ # @api private
79
+ #
80
+ def self.connect(*args)
81
+ new(Connection.build(*args))
82
+ end
83
+
84
+ end
85
+ end
@@ -0,0 +1,158 @@
1
+ module Esearch
2
+ # Abstract base class for elasticsearch commands
3
+ class Command
4
+ include Adamantium::Flat, AbstractType, Concord.new(:context)
5
+
6
+ EXPECTED_STATI = [ 200 ].freeze
7
+ JSON_CONTENT_TYPE = 'application/json; charset=UTF-8'.freeze
8
+
9
+ # Run command
10
+ #
11
+ # @return [Object]
12
+ #
13
+ # @api private
14
+ #
15
+ def self.run(*args)
16
+ new(*args).result
17
+ end
18
+
19
+ # Return result of request
20
+ #
21
+ # @return [Presenter]
22
+ #
23
+ # @api private
24
+ #
25
+ def result
26
+ assert_success
27
+ presenter.new(parsed_json)
28
+ end
29
+
30
+ private
31
+
32
+ # Test for json content type
33
+ #
34
+ # @return [true]
35
+ # if content type is json
36
+ #
37
+ # @return [false]
38
+ # otherwise
39
+ #
40
+ # @api private
41
+ #
42
+ def json_content_type?
43
+ content_type.eql?(JSON_CONTENT_TYPE)
44
+ end
45
+
46
+ # Return presenter
47
+ #
48
+ # @return [Class:Presenter]
49
+ #
50
+ # @api private
51
+ #
52
+ def presenter
53
+ self.class::PRESENTER
54
+ end
55
+
56
+ # Return connection
57
+ #
58
+ # @return [Faraday::Connection]
59
+ #
60
+ # @api private
61
+ #
62
+ def connection
63
+ context.connection
64
+ end
65
+
66
+ # Return context path
67
+ #
68
+ # @return [Pathname]
69
+ #
70
+ # @api private
71
+ #
72
+ def context_path
73
+ context.path
74
+ end
75
+
76
+ # Return response content type
77
+ #
78
+ # @return [String]
79
+ #
80
+ # @api private
81
+ #
82
+ def content_type
83
+ response.headers['content-type']
84
+ end
85
+
86
+ # Return expected response stati
87
+ #
88
+ # @return [Enumerable<Fixnum>]
89
+ #
90
+ # @api private
91
+ #
92
+ def expected_response_stati
93
+ self.class::EXPECTED_STATI
94
+ end
95
+
96
+ # Test for success
97
+ #
98
+ # @return [undefined]
99
+ #
100
+ # @api private
101
+ #
102
+ def assert_success
103
+ unless expected_response_stati.include?(response.status)
104
+ raise_status_error
105
+ end
106
+ end
107
+
108
+ # Raise remote status error
109
+ #
110
+ # @return [undefined]
111
+ #
112
+ # @api private
113
+ #
114
+ def raise_status_error
115
+ raise ProtocolError, "expected response stati: #{expected_response_stati.inspect} but got: #{response.status}, remote message: #{remote_message.inspect}"
116
+ end
117
+
118
+ # Return remote message
119
+ #
120
+ # @return [String]
121
+ #
122
+ # @api private
123
+ #
124
+ def remote_message
125
+ if json_content_type?
126
+ parsed_json
127
+ else
128
+ response.body
129
+ end
130
+ end
131
+
132
+ # Return parsed json
133
+ #
134
+ # @return [Hash]
135
+ #
136
+ # @api private
137
+ #
138
+ def parsed_json
139
+ unless json_content_type?
140
+ raise ProtocolError, "Expected json content type, but got: #{content_type.inspect}"
141
+ end
142
+ MultiJson.load(response.body)
143
+ end
144
+ memoize :parsed_json
145
+
146
+ # Return response
147
+ #
148
+ # @return [Faraday::Response]
149
+ #
150
+ # @api private
151
+ #
152
+ def response
153
+ connection.run(request)
154
+ end
155
+ memoize :response
156
+
157
+ end
158
+ end
@@ -0,0 +1,28 @@
1
+ module Esearch
2
+ class Command
3
+ # Base class for cluster commands
4
+ class Cluster < self
5
+
6
+ # Command for accessing health
7
+ class Health < self
8
+ include Concord.new(:context, :options)
9
+
10
+ PRESENTER = Presenter::Cluster::Health
11
+
12
+ private
13
+
14
+ # Return request
15
+ #
16
+ # @return [Request]
17
+ #
18
+ # @api private
19
+ #
20
+ def request
21
+ Request.get('/_cluster/health', {}, options)
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,111 @@
1
+ module Esearch
2
+ class Command
3
+
4
+ # Base class for commands on documents
5
+ class Document < self
6
+
7
+ # Document index command
8
+ class Index < self
9
+ include Concord.new(:context, :document, :options)
10
+
11
+ EXPECTED_STATI = [ 200, 201 ].freeze
12
+ PRESENTER = Presenter::Document::Operation::Index
13
+
14
+ FORCE_OPTIONS = {}
15
+
16
+ private
17
+
18
+ # Return request
19
+ #
20
+ # @return [Request]
21
+ #
22
+ # @api private
23
+ #
24
+ def request
25
+ Request.post(context_path, document, effective_options)
26
+ end
27
+
28
+ # Return effective options
29
+ #
30
+ # @return [Hash]
31
+ #
32
+ # @api private
33
+ #
34
+ def effective_options
35
+ options.merge(self.class::FORCE_OPTIONS)
36
+ end
37
+
38
+ # Document index update command
39
+ class Update < self
40
+ EXPECTED_STATI = [ 200 ].freeze
41
+ FORCE_OPTIONS = { :op_type => :index }.freeze
42
+ end
43
+
44
+ # Document index create command
45
+ class Create < self
46
+ EXPECTED_STATI = [ 201 ].freeze
47
+ FORCE_OPTIONS = { :op_type => :create }.freeze
48
+ end
49
+ end
50
+
51
+ # Present get document command result
52
+ class Get < self
53
+
54
+ EXPECTED_STATI = [ 200, 404 ].freeze
55
+ PRESENTER = Presenter::Document::Get
56
+
57
+ # Return result
58
+ #
59
+ # @return [true]
60
+ # if object exists
61
+ #
62
+ # @return [false]
63
+ # otherwise
64
+ #
65
+ # @api private
66
+ #
67
+ def result
68
+ assert_success
69
+ if response.status == 200
70
+ presenter.new(parsed_json)
71
+ else
72
+ nil
73
+ end
74
+ end
75
+
76
+ private
77
+
78
+ # Return request
79
+ #
80
+ # @return [Request]
81
+ #
82
+ # @api private
83
+ #
84
+ def request
85
+ Request.get(context_path)
86
+ end
87
+
88
+ end
89
+
90
+ # Present delete document command result
91
+ class Delete < self
92
+
93
+ PRESENTER = Presenter::Document::Operation::Delete
94
+
95
+ private
96
+
97
+ # Return request
98
+ #
99
+ # @return [Request]
100
+ #
101
+ # @api private
102
+ #
103
+ def request
104
+ Request.delete(context_path)
105
+ end
106
+
107
+ end
108
+
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,37 @@
1
+ module Esearch
2
+ class Command
3
+ # Command to check existance of objects
4
+ class Exist < self
5
+
6
+ EXPECTED_STATI = [ 200, 404 ].freeze
7
+
8
+ # Return result
9
+ #
10
+ # @return [true]
11
+ # if object exists
12
+ #
13
+ # @return [false]
14
+ # otherwise
15
+ #
16
+ # @api private
17
+ #
18
+ def result
19
+ assert_success
20
+ response.status == 200
21
+ end
22
+
23
+ private
24
+
25
+ # Return request
26
+ #
27
+ # @return [Request]
28
+ #
29
+ # @api private
30
+ #
31
+ def request
32
+ Request.head(context_path)
33
+ end
34
+
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,66 @@
1
+ module Esearch
2
+ class Command
3
+ # Base class for commands on index
4
+ class Index < self
5
+
6
+ # Create index comand
7
+ class Create < self
8
+ include Concord.new(:context, :settings)
9
+
10
+ EXPECT_STATUS = [ 201 ].freeze
11
+ PRESENTER = Presenter::Index::Create
12
+
13
+ private
14
+
15
+ # Return request
16
+ #
17
+ # @return [Request]
18
+ #
19
+ # @api private
20
+ #
21
+ def request
22
+ Request.put(context_path, settings)
23
+ end
24
+
25
+ end
26
+
27
+ # Delete index comand
28
+ class Delete < self
29
+
30
+ PRESENTER = Presenter::Index::Delete
31
+
32
+ private
33
+
34
+ # Return request
35
+ #
36
+ # @return [Request]
37
+ #
38
+ # @api private
39
+ #
40
+ def request
41
+ Request.delete(context_path)
42
+ end
43
+
44
+ end
45
+
46
+ # Refresh index command
47
+ class Refresh < self
48
+
49
+ PRESENTER = Presenter::Index::Refresh
50
+
51
+ private
52
+
53
+ # Return request
54
+ #
55
+ # @return [Request]
56
+ #
57
+ # @api private
58
+ #
59
+ def request
60
+ Request.post(context_path.join('_refresh'))
61
+ end
62
+
63
+ end
64
+ end
65
+ end
66
+ end