esearch 0.2.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.
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