stretchy 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/console +0 -0
- data/bin/setup +0 -0
- data/lib/stretchy/boosts/base.rb +17 -0
- data/lib/stretchy/boosts/filter_boost.rb +5 -1
- data/lib/stretchy/boosts/geo_boost.rb +9 -1
- data/lib/stretchy/boosts/random_boost.rb +5 -1
- data/lib/stretchy/errors/contract_error.rb +5 -0
- data/lib/stretchy/filters/and_filter.rb +4 -1
- data/lib/stretchy/filters/base.rb +17 -0
- data/lib/stretchy/filters/bool_filter.rb +7 -1
- data/lib/stretchy/filters/exists_filter.rb +1 -1
- data/lib/stretchy/filters/geo_filter.rb +8 -1
- data/lib/stretchy/filters/not_filter.rb +5 -1
- data/lib/stretchy/filters/query_filter.rb +4 -1
- data/lib/stretchy/filters/range_filter.rb +6 -1
- data/lib/stretchy/filters/terms_filter.rb +5 -1
- data/lib/stretchy/queries/base.rb +17 -0
- data/lib/stretchy/queries/filtered_query.rb +5 -1
- data/lib/stretchy/queries/function_score_query.rb +14 -24
- data/lib/stretchy/queries/match_all_query.rb +5 -1
- data/lib/stretchy/queries/match_query.rb +8 -1
- data/lib/stretchy/query.rb +1 -1
- data/lib/stretchy/utils/client_actions.rb +63 -0
- data/lib/stretchy/utils/configuration.rb +36 -0
- data/lib/stretchy/utils/contract.rb +100 -0
- data/lib/stretchy/version.rb +1 -1
- data/lib/stretchy.rb +11 -3
- metadata +9 -4
- data/lib/stretchy/client_actions.rb +0 -61
- data/lib/stretchy/configuration.rb +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 28c98af055eaf32fb6c23460780f168e66c894bb
|
4
|
+
data.tar.gz: 54af860b9fca236b64c2d95f3acbd13bde7b5f47
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b1a8077918cd57cb1294f9340716d2b20d14ce4ebaf01c96eb6e535011ebe4dafcccc013ae4ce201120f5fabe75498c823b29825a1471bf8cdc11cbe99204b23
|
7
|
+
data.tar.gz: ab509f01cfc5f0a97dd522a3ad1bd9ba34bd1c0bbdc4b863d81b78ec386f8f86fc1d3d947d53c748af5ba71f4e27ed195b80f5000e64da8be8ec8c098381064a
|
data/bin/console
CHANGED
File without changes
|
data/bin/setup
CHANGED
File without changes
|
@@ -1,12 +1,16 @@
|
|
1
1
|
module Stretchy
|
2
2
|
module Boosts
|
3
|
-
class FilterBoost
|
3
|
+
class FilterBoost < Base
|
4
4
|
|
5
5
|
DEFAULT_WEIGHT = 1.2
|
6
6
|
|
7
|
+
contract filter: {type: Stretchy::Filters::Base},
|
8
|
+
weight: {type: Numeric}
|
9
|
+
|
7
10
|
def initialize(filter:, weight: DEFAULT_WEIGHT)
|
8
11
|
@filter = filter
|
9
12
|
@weight = weight
|
13
|
+
validate!
|
10
14
|
end
|
11
15
|
|
12
16
|
def to_search
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Stretchy
|
2
2
|
module Boosts
|
3
|
-
class GeoBoost
|
3
|
+
class GeoBoost < Base
|
4
4
|
|
5
5
|
DEFAULTS = {
|
6
6
|
field: 'coords',
|
@@ -10,6 +10,13 @@ module Stretchy
|
|
10
10
|
weight: 1.2
|
11
11
|
}.freeze
|
12
12
|
|
13
|
+
contract offset: {type: :distance},
|
14
|
+
scale: {type: :distance},
|
15
|
+
decay: {type: Numeric},
|
16
|
+
weight: {type: Numeric},
|
17
|
+
lat: {type: :lat},
|
18
|
+
lng: {type: :lng}
|
19
|
+
|
13
20
|
def initialize(options = {})
|
14
21
|
@field = options[:field] || DEFAULTS[:field]
|
15
22
|
@offset = options[:offset] || DEFAULTS[:offset]
|
@@ -18,6 +25,7 @@ module Stretchy
|
|
18
25
|
@weight = options[:weight] || DEFAULTS[:weight]
|
19
26
|
@lat = options[:lat]
|
20
27
|
@lng = options[:lng]
|
28
|
+
validate!
|
21
29
|
end
|
22
30
|
|
23
31
|
def to_search
|
@@ -1,15 +1,19 @@
|
|
1
1
|
module Stretchy
|
2
2
|
module Boosts
|
3
|
-
class RandomBoost
|
3
|
+
class RandomBoost < Base
|
4
4
|
|
5
5
|
DEFAULT_WEIGHT = 1.2
|
6
6
|
|
7
|
+
contract seed: {type: Numeric},
|
8
|
+
weight: {type: Numeric}
|
9
|
+
|
7
10
|
# randomizes order (somewhat) consistently per-user
|
8
11
|
# http://www.elastic.co/guide/en/elasticsearch/guide/current/random-scoring.html
|
9
12
|
|
10
13
|
def initialize(seed, weight = DEFAULT_WEIGHT)
|
11
14
|
@seed = seed
|
12
15
|
@weight = weight
|
16
|
+
validate!
|
13
17
|
end
|
14
18
|
|
15
19
|
def to_search
|
@@ -1,10 +1,16 @@
|
|
1
1
|
module Stretchy
|
2
2
|
module Filters
|
3
|
-
class BoolFilter
|
3
|
+
class BoolFilter < Base
|
4
|
+
|
5
|
+
contract must: {type: Base, array: true},
|
6
|
+
must_not: {type: Base, array: true},
|
7
|
+
should: {type: Base, array: true}
|
8
|
+
|
4
9
|
def initialize(must:, must_not:, should: nil)
|
5
10
|
@must = Array(must)
|
6
11
|
@must_not = Array(must_not)
|
7
12
|
@should = Array(should)
|
13
|
+
validate!
|
8
14
|
end
|
9
15
|
|
10
16
|
def to_search
|
@@ -1,11 +1,18 @@
|
|
1
1
|
module Stretchy
|
2
2
|
module Filters
|
3
|
-
class GeoFilter
|
3
|
+
class GeoFilter < Base
|
4
|
+
|
5
|
+
contract distance: {type: :distance},
|
6
|
+
lat: {type: :lat},
|
7
|
+
lng: {type: :lng},
|
8
|
+
field: {type: :field}
|
9
|
+
|
4
10
|
def initialize(field: 'coords', distance: '50km', lat:, lng:)
|
5
11
|
@field = field
|
6
12
|
@distance = distance
|
7
13
|
@lat = lat
|
8
14
|
@lng = lng
|
15
|
+
validate!
|
9
16
|
end
|
10
17
|
|
11
18
|
def to_search
|
@@ -1,6 +1,8 @@
|
|
1
1
|
module Stretchy
|
2
2
|
module Filters
|
3
|
-
class NotFilter
|
3
|
+
class NotFilter < Base
|
4
|
+
|
5
|
+
contract :filter, type: Base
|
4
6
|
|
5
7
|
def initialize(filters)
|
6
8
|
filters = Array(filters)
|
@@ -10,6 +12,8 @@ module Stretchy
|
|
10
12
|
else
|
11
13
|
@filter = AndFilter.new(filters)
|
12
14
|
end
|
15
|
+
|
16
|
+
validate!
|
13
17
|
end
|
14
18
|
|
15
19
|
def to_search
|
@@ -1,10 +1,14 @@
|
|
1
1
|
module Stretchy
|
2
2
|
module Filters
|
3
|
-
class TermsFilter
|
3
|
+
class TermsFilter < Base
|
4
|
+
|
5
|
+
contract field: {type: :field},
|
6
|
+
values: {type: Array}
|
4
7
|
|
5
8
|
def initialize(field:, values:)
|
6
9
|
@field = field
|
7
10
|
@values = Array(values)
|
11
|
+
validate!
|
8
12
|
end
|
9
13
|
|
10
14
|
def to_search
|
@@ -1,10 +1,14 @@
|
|
1
1
|
module Stretchy
|
2
2
|
module Queries
|
3
|
-
class FilteredQuery
|
3
|
+
class FilteredQuery < Base
|
4
|
+
|
5
|
+
contract query: {type: Base},
|
6
|
+
filter: {type: Stretchy::Filters::Base}
|
4
7
|
|
5
8
|
def initialize(query: nil, filter:)
|
6
9
|
@query = query
|
7
10
|
@filter = filter
|
11
|
+
validate!
|
8
12
|
end
|
9
13
|
|
10
14
|
def to_search
|
@@ -1,10 +1,19 @@
|
|
1
1
|
module Stretchy
|
2
2
|
module Queries
|
3
|
-
class FunctionScoreQuery
|
3
|
+
class FunctionScoreQuery < Base
|
4
4
|
|
5
5
|
SCORE_MODES = %w(multiply sum avg first max min)
|
6
6
|
BOOST_MODES = %w(multiply replace sum avg max min)
|
7
7
|
|
8
|
+
contract functions: {responds_to: :to_search, array: true},
|
9
|
+
query: {type: Base},
|
10
|
+
filter: {type: Stretchy::Filters::Base},
|
11
|
+
score_mode: {type: String, in: SCORE_MODES},
|
12
|
+
boost_mode: {type: String, in: BOOST_MODES},
|
13
|
+
min_score: {type: Numeric},
|
14
|
+
max_boost: {type: Numeric},
|
15
|
+
boost: {type: Numeric}
|
16
|
+
|
8
17
|
def initialize(options = {})
|
9
18
|
@functions = Array(options[:functions])
|
10
19
|
@query = options[:query]
|
@@ -13,36 +22,17 @@ module Stretchy
|
|
13
22
|
self.class.attributes.map do |field|
|
14
23
|
instance_variable_set("@#{field}", options[field])
|
15
24
|
end
|
16
|
-
validate
|
25
|
+
validate!
|
26
|
+
validate_query_or_filter
|
17
27
|
end
|
18
28
|
|
19
29
|
def self.attributes
|
20
30
|
[:boost, :max_boost, :score_mode, :boost_mode, :min_score]
|
21
31
|
end
|
22
32
|
|
23
|
-
def
|
33
|
+
def validate_query_or_filter
|
24
34
|
if @query && @filter
|
25
|
-
raise
|
26
|
-
end
|
27
|
-
|
28
|
-
if @boost && !@boost.is_a?(Numeric)
|
29
|
-
raise ArgumentError.new("Boost must be a number - it is the global boost for the whole query")
|
30
|
-
end
|
31
|
-
|
32
|
-
if @max_boost && !@max_boost.is_a?(Numeric)
|
33
|
-
raise ArgumentError.new("Max boost must be a number")
|
34
|
-
end
|
35
|
-
|
36
|
-
if @min_score && !@min_score.is_a?(Numeric)
|
37
|
-
raise ArgumentError.new("min_score must be a number - it is the global boost for the whole query")
|
38
|
-
end
|
39
|
-
|
40
|
-
if @score_mode && !SCORE_MODES.include?(@score_mode)
|
41
|
-
raise ArgumentError.new("Score mode must be one of #{SCORE_MODES.join(', ')}")
|
42
|
-
end
|
43
|
-
|
44
|
-
if @boost_mode && !BOOST_MODES.include?(@boost_mode)
|
45
|
-
raise ArgumentError.new("Score mode must be one of #{BOOST_MODES.join(', ')}")
|
35
|
+
raise Stretchy::Errors::ContractError.new "Cannot have both query and filter -- combine using a FilteredQuery"
|
46
36
|
end
|
47
37
|
end
|
48
38
|
|
@@ -1,11 +1,18 @@
|
|
1
1
|
module Stretchy
|
2
2
|
module Queries
|
3
|
-
class MatchQuery
|
3
|
+
class MatchQuery < Base
|
4
|
+
|
5
|
+
OPERATORS = ['and', 'or']
|
6
|
+
|
7
|
+
contract field: {type: :field},
|
8
|
+
operator: {type: String, in: OPERATORS},
|
9
|
+
string: {type: String}
|
4
10
|
|
5
11
|
def initialize(string, field: '_all', operator: 'and')
|
6
12
|
@field = field
|
7
13
|
@operator = operator
|
8
14
|
@string = string
|
15
|
+
validate!
|
9
16
|
end
|
10
17
|
|
11
18
|
def to_search
|
data/lib/stretchy/query.rb
CHANGED
@@ -145,7 +145,7 @@ module Stretchy
|
|
145
145
|
end
|
146
146
|
|
147
147
|
def match(string, options = {})
|
148
|
-
return self if string.empty?
|
148
|
+
return self if string.nil? || string.empty?
|
149
149
|
field = options[:field] || '_all'
|
150
150
|
operator = options[:operator] || 'and'
|
151
151
|
clone_with(match: Queries::MatchQuery.new(string, field: field, operator: operator))
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'json'
|
2
|
+
module Stretchy
|
3
|
+
module Utils
|
4
|
+
module ClientActions
|
5
|
+
|
6
|
+
def self.extended(base)
|
7
|
+
unless base.respond_to?(:client) && base.respond_to?(:index_name)
|
8
|
+
raise "ClientActions requires methods 'client' and 'index_name'"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# used for ensuring a concistent index in specs
|
13
|
+
def refresh
|
14
|
+
client.indices.refresh index: index_name
|
15
|
+
end
|
16
|
+
|
17
|
+
def count
|
18
|
+
client.cat.count(index: index_name).split(' ')[2].to_i
|
19
|
+
end
|
20
|
+
|
21
|
+
def search(type:, body:, fields: nil)
|
22
|
+
options = { index: index_name, type: type, body: body }
|
23
|
+
options[:fields] = fields if fields.is_a?(Array)
|
24
|
+
|
25
|
+
client.search(options)
|
26
|
+
end
|
27
|
+
|
28
|
+
def index(type:, body:, id: nil)
|
29
|
+
id ||= body['id'] || body['_id'] || body[:id] || body[:_id]
|
30
|
+
client.index(index: index_name, type: type, id: id, body: body)
|
31
|
+
end
|
32
|
+
|
33
|
+
def bulk(type:, documents:)
|
34
|
+
requests = documents.flat_map do |document|
|
35
|
+
id = document['id'] || document['_id'] || document[:id] || document[:_id]
|
36
|
+
[
|
37
|
+
{ index: { '_index' => index_name, '_type' => type, '_id' => id } },
|
38
|
+
document
|
39
|
+
]
|
40
|
+
end
|
41
|
+
client.bulk body: requests
|
42
|
+
end
|
43
|
+
|
44
|
+
def exists(_index_name = index_name)
|
45
|
+
client.indices.exists(index: _index_name)
|
46
|
+
end
|
47
|
+
alias :exists? :exists
|
48
|
+
|
49
|
+
def delete(_index_name = index_name)
|
50
|
+
client.indices.delete(index: _index_name) if exists?(_index_name)
|
51
|
+
end
|
52
|
+
|
53
|
+
def create(_index_name = index_name)
|
54
|
+
client.indices.create(index: _index_name) unless exists?(_index_name)
|
55
|
+
end
|
56
|
+
|
57
|
+
def mapping(_index_name, _type, _body)
|
58
|
+
client.indices.put_mapping(index: _index_name, type: _type, body: _body)
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Stretchy
|
2
|
+
module Utils
|
3
|
+
module Configuration
|
4
|
+
|
5
|
+
attr_accessor :index_name, :logger, :url, :adapter, :client
|
6
|
+
|
7
|
+
def self.extended(base)
|
8
|
+
base.set_default_configuration
|
9
|
+
end
|
10
|
+
|
11
|
+
def configure
|
12
|
+
yield self
|
13
|
+
end
|
14
|
+
|
15
|
+
def set_default_configuration
|
16
|
+
self.index_name = 'myapp'
|
17
|
+
self.adapter = :excon
|
18
|
+
self.url = ENV['ELASTICSEARCH_URL']
|
19
|
+
end
|
20
|
+
|
21
|
+
def client_options
|
22
|
+
Hash[
|
23
|
+
index_name: index_name,
|
24
|
+
log: !!logger,
|
25
|
+
logger: logger,
|
26
|
+
adapter: adapter,
|
27
|
+
url: url
|
28
|
+
]
|
29
|
+
end
|
30
|
+
|
31
|
+
def client(options = {})
|
32
|
+
@client ||= Elasticsearch::Client.new(client_options.merge(options))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module Stretchy
|
2
|
+
module Utils
|
3
|
+
module Contract
|
4
|
+
|
5
|
+
ASSERTIONS = [:type, :responds_to, :in, :matches, :required]
|
6
|
+
DISTANCE_FORMAT = /^(\d+)(km|mi)$/
|
7
|
+
|
8
|
+
def self.included(base)
|
9
|
+
base.send(:extend, ClassMethods)
|
10
|
+
end
|
11
|
+
|
12
|
+
def validate!
|
13
|
+
self.class.contracts.each do |name, options|
|
14
|
+
value = instance_variable_get("@#{name}")
|
15
|
+
next if value.nil? && !options[:required]
|
16
|
+
|
17
|
+
if options[:array]
|
18
|
+
self.class.assert_type(name, value, type: Array)
|
19
|
+
end
|
20
|
+
|
21
|
+
ASSERTIONS.each do |assertion|
|
22
|
+
assertion_method = "assert_#{assertion}"
|
23
|
+
if options[:array]
|
24
|
+
value.each {|v| self.class.send(assertion_method, name, v, options) } unless options[assertion].nil?
|
25
|
+
else
|
26
|
+
self.class.send(assertion_method, name, value, options) unless options[assertion].nil?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
module ClassMethods
|
33
|
+
|
34
|
+
attr_reader :contracts
|
35
|
+
|
36
|
+
def contract(var, options = {})
|
37
|
+
@contracts ||= {}
|
38
|
+
if var.is_a?(Hash)
|
39
|
+
var.each {|k,v| @contracts[k] = v }
|
40
|
+
else
|
41
|
+
@contracts[var] = options
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def fail_assertion(msg)
|
46
|
+
raise Stretchy::Errors::ContractError.new(msg)
|
47
|
+
end
|
48
|
+
|
49
|
+
def assert_required(name, value, options)
|
50
|
+
msg = "Expected to have param #{name}, but got nil"
|
51
|
+
fail_assertion(msg) if msg.nil?
|
52
|
+
end
|
53
|
+
|
54
|
+
def assert_type(name, value, options)
|
55
|
+
type = options[:type]
|
56
|
+
case type
|
57
|
+
when :distance
|
58
|
+
msg = "Expected #{name} to be a distance measure, but #{value} is not a valid distance"
|
59
|
+
fail_assertion(msg) unless value.match(DISTANCE_FORMAT)
|
60
|
+
when :lat
|
61
|
+
msg = "Expected #{name} to be between 90 and -90, but was #{value}"
|
62
|
+
value = Float(value) rescue nil
|
63
|
+
fail_assertion(msg) unless value && value <= 90 && value >= -90
|
64
|
+
when :lng
|
65
|
+
msg = "Expected #{name} to be between 180 and -180, but was #{value}"
|
66
|
+
value = Float(value) rescue nil
|
67
|
+
fail_assertion(msg) unless value && value.to_f <= 180 && value.to_f >= -180
|
68
|
+
when :field
|
69
|
+
msg = "Expected #{name} to be a string, symbol, or number, but got #{value.class.name}"
|
70
|
+
fail_assertion(msg) unless value.is_a?(String) || value.is_a?(Symbol) || value.is_a?(Numeric)
|
71
|
+
|
72
|
+
msg = "Expected #{name} to be a string, symbol, or number, but was blank"
|
73
|
+
fail_assertion(msg) if value.is_a?(String) && value.empty?
|
74
|
+
else
|
75
|
+
msg = "Expected #{name} to be of type #{type}, but found #{value.class.name}"
|
76
|
+
fail_assertion(msg) unless value.is_a?(type)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def assert_responds_to(name, value, options)
|
81
|
+
method = options[:responds_to]
|
82
|
+
msg = "Expected #{name} to respond_to #{method}, but #{value.class.name} does not"
|
83
|
+
fail_assertion(msg) unless value.respond_to?(method)
|
84
|
+
end
|
85
|
+
|
86
|
+
def assert_in(name, value, options)
|
87
|
+
collection = options[:in]
|
88
|
+
msg = "Expected #{name} to be one of #{collection}, but got #{value}"
|
89
|
+
fail_assertion(msg) unless collection.include?(value)
|
90
|
+
end
|
91
|
+
|
92
|
+
def assert_matches(name, value, options)
|
93
|
+
matcher = options[:matches]
|
94
|
+
msg = "Expected #{name} to match #{matcher}, but #{value} does not"
|
95
|
+
fail_assertion(msg) unless matcher.match(value)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
data/lib/stretchy/version.rb
CHANGED
data/lib/stretchy.rb
CHANGED
@@ -3,12 +3,20 @@ require 'logger'
|
|
3
3
|
require 'excon'
|
4
4
|
require 'elasticsearch'
|
5
5
|
|
6
|
+
require 'stretchy/utils/contract'
|
7
|
+
require 'stretchy/utils/configuration'
|
8
|
+
require 'stretchy/utils/client_actions'
|
9
|
+
require 'stretchy/boosts/base'
|
10
|
+
require 'stretchy/filters/base'
|
11
|
+
require 'stretchy/queries/base'
|
12
|
+
|
6
13
|
Dir[File.join(File.dirname(__FILE__), 'stretchy', '**', '*.rb')].each do |path|
|
7
|
-
require path
|
14
|
+
require path unless path =~ /utils/ || path =~ /base/
|
8
15
|
end
|
9
16
|
|
10
17
|
module Stretchy
|
11
|
-
|
12
|
-
extend
|
18
|
+
|
19
|
+
extend Utils::Configuration
|
20
|
+
extend Utils::ClientActions
|
13
21
|
|
14
22
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stretchy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- agius
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-04-
|
11
|
+
date: 2015-04-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: elasticsearch
|
@@ -109,12 +109,13 @@ files:
|
|
109
109
|
- bin/console
|
110
110
|
- bin/setup
|
111
111
|
- lib/stretchy.rb
|
112
|
+
- lib/stretchy/boosts/base.rb
|
112
113
|
- lib/stretchy/boosts/filter_boost.rb
|
113
114
|
- lib/stretchy/boosts/geo_boost.rb
|
114
115
|
- lib/stretchy/boosts/random_boost.rb
|
115
|
-
- lib/stretchy/
|
116
|
-
- lib/stretchy/configuration.rb
|
116
|
+
- lib/stretchy/errors/contract_error.rb
|
117
117
|
- lib/stretchy/filters/and_filter.rb
|
118
|
+
- lib/stretchy/filters/base.rb
|
118
119
|
- lib/stretchy/filters/bool_filter.rb
|
119
120
|
- lib/stretchy/filters/exists_filter.rb
|
120
121
|
- lib/stretchy/filters/geo_filter.rb
|
@@ -123,12 +124,16 @@ files:
|
|
123
124
|
- lib/stretchy/filters/range_filter.rb
|
124
125
|
- lib/stretchy/filters/terms_filter.rb
|
125
126
|
- lib/stretchy/null_query.rb
|
127
|
+
- lib/stretchy/queries/base.rb
|
126
128
|
- lib/stretchy/queries/filtered_query.rb
|
127
129
|
- lib/stretchy/queries/function_score_query.rb
|
128
130
|
- lib/stretchy/queries/match_all_query.rb
|
129
131
|
- lib/stretchy/queries/match_query.rb
|
130
132
|
- lib/stretchy/query.rb
|
131
133
|
- lib/stretchy/request_body.rb
|
134
|
+
- lib/stretchy/utils/client_actions.rb
|
135
|
+
- lib/stretchy/utils/configuration.rb
|
136
|
+
- lib/stretchy/utils/contract.rb
|
132
137
|
- lib/stretchy/version.rb
|
133
138
|
- stretchy.gemspec
|
134
139
|
homepage: https://github.com/hired/stretchy
|
@@ -1,61 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
module Stretchy
|
3
|
-
module ClientActions
|
4
|
-
|
5
|
-
def self.extended(base)
|
6
|
-
unless base.respond_to?(:client) && base.respond_to?(:index_name)
|
7
|
-
raise "ClientActions requires methods 'client' and 'index_name'"
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
# used for ensuring a concistent index in specs
|
12
|
-
def refresh
|
13
|
-
client.indices.refresh index: index_name
|
14
|
-
end
|
15
|
-
|
16
|
-
def count
|
17
|
-
client.cat.count(index: index_name).split(' ')[2].to_i
|
18
|
-
end
|
19
|
-
|
20
|
-
def search(type:, body:, fields: nil)
|
21
|
-
options = { index: index_name, type: type, body: body }
|
22
|
-
options[:fields] = fields if fields.is_a?(Array)
|
23
|
-
|
24
|
-
client.search(options)
|
25
|
-
end
|
26
|
-
|
27
|
-
def index(type:, body:, id: nil)
|
28
|
-
id ||= body['id'] || body['_id'] || body[:id] || body[:_id]
|
29
|
-
client.index(index: index_name, type: type, id: id, body: body)
|
30
|
-
end
|
31
|
-
|
32
|
-
def bulk(type:, documents:)
|
33
|
-
requests = documents.flat_map do |document|
|
34
|
-
id = document['id'] || document['_id'] || document[:id] || document[:_id]
|
35
|
-
[
|
36
|
-
{ index: { '_index' => index_name, '_type' => type, '_id' => id } },
|
37
|
-
document
|
38
|
-
]
|
39
|
-
end
|
40
|
-
client.bulk body: requests
|
41
|
-
end
|
42
|
-
|
43
|
-
def exists(_index_name = index_name)
|
44
|
-
client.indices.exists(index: _index_name)
|
45
|
-
end
|
46
|
-
alias :exists? :exists
|
47
|
-
|
48
|
-
def delete(_index_name = index_name)
|
49
|
-
client.indices.delete(index: _index_name) if exists?(_index_name)
|
50
|
-
end
|
51
|
-
|
52
|
-
def create(_index_name = index_name)
|
53
|
-
client.indices.create(index: _index_name) unless exists?(_index_name)
|
54
|
-
end
|
55
|
-
|
56
|
-
def mapping(_index_name, _type, _body)
|
57
|
-
client.indices.put_mapping(index: _index_name, type: _type, body: _body)
|
58
|
-
end
|
59
|
-
|
60
|
-
end
|
61
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
module Stretchy
|
2
|
-
module Configuration
|
3
|
-
|
4
|
-
attr_accessor :index_name, :logger, :url, :adapter, :client
|
5
|
-
|
6
|
-
def self.extended(base)
|
7
|
-
base.set_default_configuration
|
8
|
-
end
|
9
|
-
|
10
|
-
def configure
|
11
|
-
yield self
|
12
|
-
end
|
13
|
-
|
14
|
-
def set_default_configuration
|
15
|
-
self.index_name = 'myapp'
|
16
|
-
self.adapter = :excon
|
17
|
-
self.url = ENV['ELASTICSEARCH_URL']
|
18
|
-
end
|
19
|
-
|
20
|
-
def client_options
|
21
|
-
Hash[
|
22
|
-
index_name: index_name,
|
23
|
-
log: !!logger,
|
24
|
-
logger: logger,
|
25
|
-
adapter: adapter,
|
26
|
-
url: url
|
27
|
-
]
|
28
|
-
end
|
29
|
-
|
30
|
-
def client(options = {})
|
31
|
-
@client ||= Elasticsearch::Client.new(client_options.merge(options))
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|