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.
- checksums.yaml +4 -4
- data/lib/elastic_adapter.rb +11 -9
- data/lib/elastic_adapter/index.rb +6 -4
- data/lib/elastic_adapter/{decoration → responses}/aggregation_response.rb +7 -13
- data/lib/elastic_adapter/responses/base_response.rb +28 -0
- data/lib/elastic_adapter/responses/count_response.rb +13 -0
- data/lib/elastic_adapter/responses/get_response.rb +13 -0
- data/lib/elastic_adapter/{decoration → responses}/response_decorator_factory.rb +5 -23
- data/lib/elastic_adapter/responses/sanitized_response.rb +46 -0
- data/lib/elastic_adapter/responses/search_response.rb +21 -0
- data/lib/elastic_adapter/responses/suggestion_response.rb +46 -0
- data/lib/elastic_adapter/responses/validation_response.rb +18 -0
- data/lib/elastic_adapter/version.rb +1 -1
- data/spec/cassettes/ElasticAdapter_Index/_count/empty_index/is_a_fixnum.yml +30 -0
- data/spec/cassettes/ElasticAdapter_Index/_count/empty_index/number.yml +57 -0
- data/spec/cassettes/ElasticAdapter_Index/_count/not_empty_index/is_a_fixnum.yml +30 -0
- data/spec/cassettes/ElasticAdapter_Index/_get/document_exists.yml +3 -3
- data/spec/cassettes/ElasticAdapter_Index/_get/document_exists/response/{contains_the_document.yml → document/returns_the_document.yml} +1 -1
- data/spec/cassettes/ElasticAdapter_Index/_search.yml +16 -16
- data/spec/cassettes/ElasticAdapter_Index/_search/match_all/returns_all_documents.yml +2 -2
- data/spec/cassettes/ElasticAdapter_Index/_search/zoo/returns_one_document.yml +1 -1
- data/spec/cassettes/ElasticAdapter_Index/_search/zoo/returns_the_wanted_document.yml +2 -2
- data/spec/cassettes/ElasticAdapter_Index/_validate.yml +2 -2
- data/spec/cassettes/ElasticAdapter_Index/_validate/invalid_query/is_a_response.yml +1 -1
- data/spec/cassettes/ElasticAdapter_Index/_validate/invalid_query/{is_false.yml → valid_/is_false.yml} +1 -1
- data/spec/cassettes/ElasticAdapter_Index/_validate/valid_query/is_a_response.yml +1 -1
- data/spec/cassettes/ElasticAdapter_Index/_validate/valid_query/is_true.yml +1 -1
- data/spec/index/aggregation_spec.rb +1 -1
- data/spec/index/count_spec.rb +4 -4
- data/spec/index/get_spec.rb +4 -2
- data/spec/index/index_spec.rb +1 -1
- data/spec/index/search_spec.rb +4 -4
- data/spec/index/shared_examples.rb +2 -2
- data/spec/index/suggest_spec.rb +2 -3
- data/spec/index/validate_spec.rb +7 -5
- data/spec/{decoration → responses}/aggregation_response_spec.rb +1 -2
- data/spec/responses/base_response_spec.rb +19 -0
- data/spec/responses/count_response_spec.rb +24 -0
- data/spec/responses/get_response_spec.rb +29 -0
- data/spec/{decoration → responses}/response_decorator_factory_spec.rb +54 -6
- data/spec/responses/sanitized_response_spec.rb +36 -0
- data/spec/responses/search_response_spec.rb +43 -0
- data/spec/responses/suggestion_response_spec.rb +63 -0
- data/spec/responses/validation_response_spec.rb +45 -0
- metadata +38 -20
- data/lib/elastic_adapter/decoration/count_response.rb +0 -16
- data/lib/elastic_adapter/decoration/decorator.rb +0 -37
- data/lib/elastic_adapter/decoration/hit_decorator.rb +0 -25
- data/lib/elastic_adapter/decoration/search_response.rb +0 -27
- data/lib/elastic_adapter/decoration/suggestion_response.rb +0 -24
- data/lib/elastic_adapter/decoration/validation_response.rb +0 -15
- data/lib/elastic_adapter/response.rb +0 -51
- data/spec/response_spec.rb +0 -64
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1b73e1ccef696aa67e9fdb445fdad0233735e09f
|
4
|
+
data.tar.gz: 7798c15828d65100a7586084d0b04596fa27e8f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 136c4240dfdc3cf631706b802960e42d4b73500c248635f7330791a744fc831dd6c6e27681f55f9a2869468fe0757dc18ebe499f0b4a0a384d5a4ae6a06e577b
|
7
|
+
data.tar.gz: c65ce37d0765ccee7222c746e9b7ffbbfa5817426bb427f1bc41a8de307c26ccfccef0b2f08b61f27815d6df165558a567048ef2e16c958eb2a4559d9f64fdca
|
data/lib/elastic_adapter.rb
CHANGED
@@ -2,15 +2,17 @@ require "elasticsearch"
|
|
2
2
|
|
3
3
|
require "elastic_adapter/version"
|
4
4
|
require "elastic_adapter/document_type"
|
5
|
-
|
6
|
-
require "elastic_adapter/
|
7
|
-
require "elastic_adapter/
|
8
|
-
require "elastic_adapter/
|
9
|
-
require "elastic_adapter/
|
10
|
-
require "elastic_adapter/
|
11
|
-
require "elastic_adapter/
|
12
|
-
require "elastic_adapter/
|
13
|
-
require "elastic_adapter/
|
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 :
|
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
|
-
|
209
|
+
Responses::ResponseDecoratorFactory.decorate(yield, *args)
|
208
210
|
rescue Elasticsearch::Transport::Transport::Error => e
|
209
|
-
|
211
|
+
Responses::SanitizedResponse.new(
|
210
212
|
exception: e
|
211
213
|
)
|
212
214
|
end
|
@@ -1,20 +1,16 @@
|
|
1
1
|
module ElasticAdapter
|
2
|
-
module
|
3
|
-
|
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
|
-
|
10
|
-
|
11
|
-
|
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
|
-
|
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
|
@@ -1,22 +1,20 @@
|
|
1
1
|
module ElasticAdapter
|
2
|
-
module
|
3
|
-
# This class is used
|
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
|
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 =
|
14
|
+
response = SanitizedResponse.new(plain_response)
|
17
15
|
|
18
16
|
response = CountResponse.new(response) if args.include? :count
|
19
|
-
response =
|
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
|
@@ -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
|