elastic_adapter 0.0.3 → 0.0.4

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 (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