elastic_adapter 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/lib/elastic_adapter.rb +11 -9
  3. data/lib/elastic_adapter/index.rb +6 -4
  4. data/lib/elastic_adapter/{decoration → responses}/aggregation_response.rb +7 -13
  5. data/lib/elastic_adapter/responses/base_response.rb +28 -0
  6. data/lib/elastic_adapter/responses/count_response.rb +13 -0
  7. data/lib/elastic_adapter/responses/get_response.rb +13 -0
  8. data/lib/elastic_adapter/{decoration → responses}/response_decorator_factory.rb +5 -23
  9. data/lib/elastic_adapter/responses/sanitized_response.rb +46 -0
  10. data/lib/elastic_adapter/responses/search_response.rb +21 -0
  11. data/lib/elastic_adapter/responses/suggestion_response.rb +46 -0
  12. data/lib/elastic_adapter/responses/validation_response.rb +18 -0
  13. data/lib/elastic_adapter/version.rb +1 -1
  14. data/spec/cassettes/ElasticAdapter_Index/_count/empty_index/is_a_fixnum.yml +30 -0
  15. data/spec/cassettes/ElasticAdapter_Index/_count/empty_index/number.yml +57 -0
  16. data/spec/cassettes/ElasticAdapter_Index/_count/not_empty_index/is_a_fixnum.yml +30 -0
  17. data/spec/cassettes/ElasticAdapter_Index/_get/document_exists.yml +3 -3
  18. data/spec/cassettes/ElasticAdapter_Index/_get/document_exists/response/{contains_the_document.yml → document/returns_the_document.yml} +1 -1
  19. data/spec/cassettes/ElasticAdapter_Index/_search.yml +16 -16
  20. data/spec/cassettes/ElasticAdapter_Index/_search/match_all/returns_all_documents.yml +2 -2
  21. data/spec/cassettes/ElasticAdapter_Index/_search/zoo/returns_one_document.yml +1 -1
  22. data/spec/cassettes/ElasticAdapter_Index/_search/zoo/returns_the_wanted_document.yml +2 -2
  23. data/spec/cassettes/ElasticAdapter_Index/_validate.yml +2 -2
  24. data/spec/cassettes/ElasticAdapter_Index/_validate/invalid_query/is_a_response.yml +1 -1
  25. data/spec/cassettes/ElasticAdapter_Index/_validate/invalid_query/{is_false.yml → valid_/is_false.yml} +1 -1
  26. data/spec/cassettes/ElasticAdapter_Index/_validate/valid_query/is_a_response.yml +1 -1
  27. data/spec/cassettes/ElasticAdapter_Index/_validate/valid_query/is_true.yml +1 -1
  28. data/spec/index/aggregation_spec.rb +1 -1
  29. data/spec/index/count_spec.rb +4 -4
  30. data/spec/index/get_spec.rb +4 -2
  31. data/spec/index/index_spec.rb +1 -1
  32. data/spec/index/search_spec.rb +4 -4
  33. data/spec/index/shared_examples.rb +2 -2
  34. data/spec/index/suggest_spec.rb +2 -3
  35. data/spec/index/validate_spec.rb +7 -5
  36. data/spec/{decoration → responses}/aggregation_response_spec.rb +1 -2
  37. data/spec/responses/base_response_spec.rb +19 -0
  38. data/spec/responses/count_response_spec.rb +24 -0
  39. data/spec/responses/get_response_spec.rb +29 -0
  40. data/spec/{decoration → responses}/response_decorator_factory_spec.rb +54 -6
  41. data/spec/responses/sanitized_response_spec.rb +36 -0
  42. data/spec/responses/search_response_spec.rb +43 -0
  43. data/spec/responses/suggestion_response_spec.rb +63 -0
  44. data/spec/responses/validation_response_spec.rb +45 -0
  45. metadata +38 -20
  46. data/lib/elastic_adapter/decoration/count_response.rb +0 -16
  47. data/lib/elastic_adapter/decoration/decorator.rb +0 -37
  48. data/lib/elastic_adapter/decoration/hit_decorator.rb +0 -25
  49. data/lib/elastic_adapter/decoration/search_response.rb +0 -27
  50. data/lib/elastic_adapter/decoration/suggestion_response.rb +0 -24
  51. data/lib/elastic_adapter/decoration/validation_response.rb +0 -15
  52. data/lib/elastic_adapter/response.rb +0 -51
  53. data/spec/response_spec.rb +0 -64
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 25e0579bbeba803053caee8b5986f7b02f7f719c
4
- data.tar.gz: 1280437e020532bc8c67fc55555fad96ac9bd1e8
3
+ metadata.gz: 1b73e1ccef696aa67e9fdb445fdad0233735e09f
4
+ data.tar.gz: 7798c15828d65100a7586084d0b04596fa27e8f5
5
5
  SHA512:
6
- metadata.gz: 577612284345aea4de48577b3d01c462326605e0b16531947fea2366c0ec5e4e43eac8a1687ed6942db07d559a992e29b41195d89e20e24f39d4e03a0ff84a3a
7
- data.tar.gz: ef247ad391ecc75e53f322f9a8fb659a26eb2de46f4cbd50354428a146a35028beccdf70687c043d1818cc1a578664b4bb45b7fdd99171634854ce59ef273840
6
+ metadata.gz: 136c4240dfdc3cf631706b802960e42d4b73500c248635f7330791a744fc831dd6c6e27681f55f9a2869468fe0757dc18ebe499f0b4a0a384d5a4ae6a06e577b
7
+ data.tar.gz: c65ce37d0765ccee7222c746e9b7ffbbfa5817426bb427f1bc41a8de307c26ccfccef0b2f08b61f27815d6df165558a567048ef2e16c958eb2a4559d9f64fdca
@@ -2,15 +2,17 @@ require "elasticsearch"
2
2
 
3
3
  require "elastic_adapter/version"
4
4
  require "elastic_adapter/document_type"
5
- require "elastic_adapter/decoration/decorator"
6
- require "elastic_adapter/decoration/hit_decorator"
7
- require "elastic_adapter/decoration/count_response"
8
- require "elastic_adapter/decoration/validation_response"
9
- require "elastic_adapter/decoration/suggestion_response"
10
- require "elastic_adapter/decoration/search_response"
11
- require "elastic_adapter/decoration/aggregation_response"
12
- require "elastic_adapter/decoration/response_decorator_factory"
13
- require "elastic_adapter/response"
5
+
6
+ require "elastic_adapter/responses/base_response"
7
+ require "elastic_adapter/responses/sanitized_response"
8
+ require "elastic_adapter/responses/aggregation_response"
9
+ require "elastic_adapter/responses/count_response"
10
+ require "elastic_adapter/responses/get_response"
11
+ require "elastic_adapter/responses/search_response"
12
+ require "elastic_adapter/responses/suggestion_response"
13
+ require "elastic_adapter/responses/validation_response"
14
+ require "elastic_adapter/responses/response_decorator_factory"
15
+
14
16
  require "elastic_adapter/index"
15
17
 
16
18
  begin
@@ -85,9 +85,11 @@ module ElasticAdapter
85
85
  # @param [Hash] query a query to count the documents for a given query. Defaults to match all
86
86
  # @return [Decoration::CountResponse] the count
87
87
  def count(query = { query: { match_all: {} } })
88
- handle_api_call :count do
88
+ response = handle_api_call :count do
89
89
  client.count index: name, body: query
90
90
  end
91
+
92
+ response.count || response
91
93
  end
92
94
 
93
95
  # Indexes a Hash or anything that responds to to_hash as a document
@@ -125,7 +127,7 @@ module ElasticAdapter
125
127
  # @param [Integer] id
126
128
  # @return [ElasticAdapter::HitDecorator]
127
129
  def get(id)
128
- handle_api_call :hit do
130
+ handle_api_call :get do
129
131
  client.get(
130
132
  index: name,
131
133
  type: document_type.name,
@@ -204,9 +206,9 @@ module ElasticAdapter
204
206
  private
205
207
 
206
208
  def handle_api_call(*args)
207
- Decoration::ResponseDecoratorFactory.decorate(yield, *args)
209
+ Responses::ResponseDecoratorFactory.decorate(yield, *args)
208
210
  rescue Elasticsearch::Transport::Transport::Error => e
209
- Response.new(
211
+ Responses::SanitizedResponse.new(
210
212
  exception: e
211
213
  )
212
214
  end
@@ -1,20 +1,16 @@
1
1
  module ElasticAdapter
2
- module Decoration
3
- # Used to decorate responses from the elasticsearch search api
4
- #
5
- # @attr_reader [Hash] aggregations
6
- class AggregationResponse < Decorator
2
+ module Responses
3
+ class AggregationResponse < BaseResponse
7
4
  attr_reader :aggregations
8
5
 
9
- # Reduces the interface
10
- #
11
- # @param [Hash] hash
12
- # @return [Hash]
13
- def alter_object(hash)
6
+ private
7
+
8
+ def set_instance_variables
14
9
  new_hash = {}
10
+
15
11
  new_hash[:aggregations] = {}
16
12
 
17
- hash[:aggregations].each do |key, value|
13
+ object[:aggregations].each do |key, value|
18
14
  new_hash[:aggregations][key] = []
19
15
 
20
16
  value[:buckets].each do |agg|
@@ -26,8 +22,6 @@ module ElasticAdapter
26
22
  end
27
23
 
28
24
  @aggregations = new_hash[:aggregations]
29
-
30
- new_hash
31
25
  end
32
26
  end
33
27
  end
@@ -0,0 +1,28 @@
1
+ require "delegate"
2
+
3
+ module ElasticAdapter
4
+ module Responses
5
+ class BaseResponse < SimpleDelegator
6
+ def initialize(object)
7
+ __setobj__(object)
8
+ set_instance_variables
9
+ end
10
+
11
+ # Returns the underlaying object
12
+ #
13
+ # @return [Object] The underlaying object
14
+ def object
15
+ __getobj__
16
+ end
17
+
18
+ private
19
+
20
+ # This method is intended to set instance variables that provide
21
+ # access to values from the original object
22
+ #
23
+ # @param [Object] object
24
+ def set_instance_variables
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,13 @@
1
+ module ElasticAdapter
2
+ module Responses
3
+ class CountResponse < BaseResponse
4
+ attr_reader :count
5
+
6
+ private
7
+
8
+ def set_instance_variables
9
+ @count = object[:count]
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module ElasticAdapter
2
+ module Responses
3
+ class GetResponse < BaseResponse
4
+ attr_reader :document
5
+
6
+ private
7
+
8
+ def set_instance_variables
9
+ @document = object[:source].merge(id: object[:id])
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,22 +1,20 @@
1
1
  module ElasticAdapter
2
- module Decoration
3
- # This class is used inside the Response and is used to determin
4
- # the decorator for responses returned by elasticsearch
2
+ module Responses
3
+ # This class is used to decorate responses
5
4
  #
6
- # @see Response#decorate
7
5
  class ResponseDecoratorFactory
8
6
  class << self
9
- # Takes a response and multiple symbols and decorated response.
7
+ # Takes a response and multiple symbols and decorates the response.
10
8
  #
11
9
  # @param [Hash] response a response returned by elasticsearch
12
10
  # @param [Array<Symbol>] args the decorators the response should be decorated with.
13
11
  # Currently valid args are :count, :hit, :search, :validation, :suggestion
14
12
  # @return [Docorator] a decorated response
15
13
  def decorate(plain_response, *args)
16
- response = Response.new(plain_response)
14
+ response = SanitizedResponse.new(plain_response)
17
15
 
18
16
  response = CountResponse.new(response) if args.include? :count
19
- response = HitDecorator.new(response) if args.include? :hit
17
+ response = GetResponse.new(response) if args.include? :get
20
18
  response = SearchResponse.new(response) if args.include? :search
21
19
  response = ValidationResponse.new(response) if args.include? :validation
22
20
  response = SuggestionResponse.new(response) if args.include? :suggestion
@@ -24,22 +22,6 @@ module ElasticAdapter
24
22
 
25
23
  response
26
24
  end
27
-
28
- private
29
-
30
- # Checks if the passed response is a response
31
- # from the elasticsearch suggest api
32
- #
33
- # @param [Hash] response
34
- # @return [Boolean]
35
- def suggestion?(response)
36
- second_key = response[response.keys[1]]
37
- return false unless second_key.is_a? Array
38
- return false if second_key.empty?
39
- return false unless second_key.first.is_a? Hash
40
- return false unless second_key.first.key? :options
41
- true
42
- end
43
25
  end
44
26
  end
45
27
  end
@@ -0,0 +1,46 @@
1
+ module ElasticAdapter
2
+ module Responses
3
+ class SanitizedResponse < BaseResponse
4
+ def initialize(object)
5
+ super(deep_sanitize_object(object))
6
+ end
7
+
8
+ private
9
+
10
+ def deep_sanitize_object(object)
11
+ if object.is_a? Hash
12
+ return sanitize_hash(object)
13
+ elsif object.is_a? Array
14
+ return sanitize_array(object)
15
+ else
16
+ return object
17
+ end
18
+ end
19
+
20
+ def sanitize_hash(hash)
21
+ result = {}
22
+
23
+ hash.each do |key, value|
24
+ new_key = remove_leading_underscore(key).to_sym
25
+
26
+ if value.is_a?(Hash)
27
+ result[new_key] = sanitize_hash(value)
28
+ else
29
+ result[new_key] = deep_sanitize_object(value)
30
+ end
31
+ end
32
+
33
+ result
34
+ end
35
+
36
+ def sanitize_array(array)
37
+ array.map { |element| deep_sanitize_object(element) }
38
+ end
39
+
40
+ def remove_leading_underscore(string)
41
+ /^_?(.*)$/.match(string)[1]
42
+ end
43
+ end
44
+ end
45
+ end
46
+
@@ -0,0 +1,21 @@
1
+ module ElasticAdapter
2
+ module Responses
3
+ class SearchResponse < BaseResponse
4
+ attr_reader :hits
5
+
6
+ private
7
+
8
+ def set_instance_variables
9
+ hits = []
10
+ object[:hits][:hits].each do |hit|
11
+ hits << {
12
+ id: hit[:id]
13
+ }.merge(hit[:source])
14
+
15
+ end
16
+
17
+ @hits = hits
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,46 @@
1
+ module ElasticAdapter
2
+ module Responses
3
+ class SuggestionResponse < BaseResponse
4
+ # This class represents a search term and it's
5
+ # suggested options
6
+ class TermSuggestion
7
+ attr_reader :text, :options
8
+
9
+ def initialize(params)
10
+ @text = params[:text]
11
+ @options = params[:options]
12
+ end
13
+ end
14
+
15
+ # This class represents a single named suggestion
16
+ # returned by elaticsearch
17
+ class Suggestion
18
+ attr_reader :name, :terms
19
+
20
+ def initialize(name, suggestions)
21
+ @name = name
22
+ @terms = []
23
+
24
+ suggestions.each do |suggestion_per_term|
25
+ @terms << TermSuggestion.new(suggestion_per_term)
26
+ end
27
+ end
28
+ end
29
+
30
+ attr_reader :suggestions
31
+
32
+ private
33
+
34
+ def set_instance_variables
35
+ @suggestions = []
36
+
37
+ object_without_shards = object.reject { |key, value| key == :shards}
38
+ object_without_shards.each do |key, value|
39
+ # In this context key is the named suggestion
40
+ # returned by elasticsearch
41
+ @suggestions << Suggestion.new(key, value)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,18 @@
1
+ module ElasticAdapter
2
+ module Responses
3
+ class ValidationResponse < BaseResponse
4
+ attr_reader :explanations, :valid
5
+
6
+ def valid?
7
+ valid
8
+ end
9
+
10
+ private
11
+
12
+ def set_instance_variables
13
+ @valid = object[:valid]
14
+ @explanations = object[:explanations]
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,3 +1,3 @@
1
1
  module ElasticAdapter
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -0,0 +1,30 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: http://localhost:9200/test_index/_count
6
+ body:
7
+ encoding: UTF-8
8
+ string: '{"query":{"match_all":{}}}'
9
+ headers:
10
+ User-Agent:
11
+ - Faraday v0.9.1
12
+ Accept-Encoding:
13
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
14
+ Accept:
15
+ - "*/*"
16
+ response:
17
+ status:
18
+ code: 404
19
+ message: Not Found
20
+ headers:
21
+ Content-Type:
22
+ - application/json; charset=UTF-8
23
+ Content-Length:
24
+ - '68'
25
+ body:
26
+ encoding: UTF-8
27
+ string: '{"error":"IndexMissingException[[test_index] missing]","status":404}'
28
+ http_version:
29
+ recorded_at: Mon, 09 Mar 2015 18:08:20 GMT
30
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,57 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: http://localhost:9200/test_index/_count
6
+ body:
7
+ encoding: UTF-8
8
+ string: '{"query":{"match_all":{}}}'
9
+ headers:
10
+ User-Agent:
11
+ - Faraday v0.9.1
12
+ Accept-Encoding:
13
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
14
+ Accept:
15
+ - "*/*"
16
+ response:
17
+ status:
18
+ code: 404
19
+ message: Not Found
20
+ headers:
21
+ Content-Type:
22
+ - application/json; charset=UTF-8
23
+ Content-Length:
24
+ - '68'
25
+ body:
26
+ encoding: UTF-8
27
+ string: '{"error":"IndexMissingException[[test_index] missing]","status":404}'
28
+ http_version:
29
+ recorded_at: Mon, 09 Mar 2015 18:08:00 GMT
30
+ - request:
31
+ method: get
32
+ uri: http://localhost:9200/test_index/_count
33
+ body:
34
+ encoding: UTF-8
35
+ string: '{"query":{"match_all":{}}}'
36
+ headers:
37
+ User-Agent:
38
+ - Faraday v0.9.1
39
+ Accept-Encoding:
40
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
41
+ Accept:
42
+ - "*/*"
43
+ response:
44
+ status:
45
+ code: 404
46
+ message: Not Found
47
+ headers:
48
+ Content-Type:
49
+ - application/json; charset=UTF-8
50
+ Content-Length:
51
+ - '68'
52
+ body:
53
+ encoding: UTF-8
54
+ string: '{"error":"IndexMissingException[[test_index] missing]","status":404}'
55
+ http_version:
56
+ recorded_at: Mon, 09 Mar 2015 18:08:02 GMT
57
+ recorded_with: VCR 2.9.3