stretchy 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/stretchy/boosts/base.rb +2 -0
- data/lib/stretchy/boosts/filter_boost.rb +4 -4
- data/lib/stretchy/boosts/random_boost.rb +2 -2
- data/lib/stretchy/builders/boost_builder.rb +36 -0
- data/lib/stretchy/builders/match_builder.rb +44 -0
- data/lib/stretchy/builders/where_builder.rb +126 -0
- data/lib/stretchy/clauses/base.rb +95 -0
- data/lib/stretchy/clauses/boost_clause.rb +50 -0
- data/lib/stretchy/clauses/boost_match_clause.rb +31 -0
- data/lib/stretchy/clauses/boost_where_clause.rb +44 -0
- data/lib/stretchy/clauses/match_clause.rb +57 -0
- data/lib/stretchy/clauses/where_clause.rb +113 -0
- data/lib/stretchy/filters/and_filter.rb +6 -2
- data/lib/stretchy/filters/bool_filter.rb +8 -7
- data/lib/stretchy/filters/exists_filter.rb +3 -0
- data/lib/stretchy/filters/geo_filter.rb +9 -9
- data/lib/stretchy/filters/range_filter.rb +8 -6
- data/lib/stretchy/filters/terms_filter.rb +17 -9
- data/lib/stretchy/queries/bool_query.rb +21 -0
- data/lib/stretchy/queries/filtered_query.rb +4 -3
- data/lib/stretchy/queries/function_score_query.rb +1 -1
- data/lib/stretchy/queries/match_query.rb +12 -5
- data/lib/stretchy/results/base.rb +45 -0
- data/lib/stretchy/results/null_results.rb +22 -0
- data/lib/stretchy/utils/contract.rb +16 -1
- data/lib/stretchy/version.rb +1 -1
- data/lib/stretchy.rb +12 -3
- data/stretchy.gemspec +6 -4
- metadata +42 -5
- data/lib/stretchy/null_query.rb +0 -30
- data/lib/stretchy/query.rb +0 -241
- data/lib/stretchy/request_body.rb +0 -67
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 02cee68659326cb0fcbb36e25b584efd846149cc
|
4
|
+
data.tar.gz: 4af82a79df5998f4bf7beface88f4467425fd86a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 432060e10838aa8438d545ff402214d9b4048d5848f1dbefde4d0a4fff4be366b51dfe52642d02628b61462679c0a7ee513035acd9dd2cd6c5604cb2ac1b64ec
|
7
|
+
data.tar.gz: 98a4e9114c0b8a99687773994ab45bbc32a07621cb48a7cb41f6e132e0d3dc975211ed091a99a686739efee9010742219ede298b3d0402da75a92e353f718e90
|
data/lib/stretchy/boosts/base.rb
CHANGED
@@ -2,14 +2,14 @@ module Stretchy
|
|
2
2
|
module Boosts
|
3
3
|
class FilterBoost < Base
|
4
4
|
|
5
|
-
|
5
|
+
attr_reader :filter, :weight
|
6
6
|
|
7
7
|
contract filter: {type: Stretchy::Filters::Base},
|
8
8
|
weight: {type: Numeric}
|
9
9
|
|
10
|
-
def initialize(
|
11
|
-
@filter = filter
|
12
|
-
@weight = weight
|
10
|
+
def initialize(options = {})
|
11
|
+
@filter = options[:filter]
|
12
|
+
@weight = options[:weight] || DEFAULT_WEIGHT
|
13
13
|
validate!
|
14
14
|
end
|
15
15
|
|
@@ -10,9 +10,9 @@ module Stretchy
|
|
10
10
|
# randomizes order (somewhat) consistently per-user
|
11
11
|
# http://www.elastic.co/guide/en/elasticsearch/guide/current/random-scoring.html
|
12
12
|
|
13
|
-
def initialize(seed, weight =
|
13
|
+
def initialize(seed, weight = nil)
|
14
14
|
@seed = seed
|
15
|
-
@weight = weight
|
15
|
+
@weight = weight || DEFAULT_WEIGHT
|
16
16
|
validate!
|
17
17
|
end
|
18
18
|
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Stretchy
|
2
|
+
module Builders
|
3
|
+
class BoostBuilder
|
4
|
+
|
5
|
+
attr_accessor :functions, :overall_boost, :max_boost, :score_mode, :boost_mode
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@functions = []
|
9
|
+
@overall_boost = nil
|
10
|
+
@max_boost = nil
|
11
|
+
@score_mode = 'sum'
|
12
|
+
@boost_mode = 'sum'
|
13
|
+
end
|
14
|
+
|
15
|
+
def any?
|
16
|
+
@functions.any?
|
17
|
+
end
|
18
|
+
|
19
|
+
def build(query_or_filter)
|
20
|
+
options = {
|
21
|
+
functions: @functions,
|
22
|
+
score_mode: @score_mode,
|
23
|
+
boost_mode: @boost_mode
|
24
|
+
}
|
25
|
+
|
26
|
+
options[:overall_boost] = @overall_boost if @overall_boost
|
27
|
+
options[:max_boost] = @max_boost if @max_boost
|
28
|
+
options[:query] = query_or_filter if query_or_filter.is_a?(Stretchy::Queries::Base)
|
29
|
+
options[:filter] = query_or_filter if query_or_filter.is_a?(Stretchy::Filters::Base)
|
30
|
+
|
31
|
+
Stretchy::Queries::FunctionScoreQuery.new(options)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Stretchy
|
2
|
+
module Builders
|
3
|
+
class MatchBuilder
|
4
|
+
|
5
|
+
attr_accessor :matches, :antimatches
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@matches = Hash.new { [] }
|
9
|
+
@antimatches = Hash.new { [] }
|
10
|
+
end
|
11
|
+
|
12
|
+
def any?
|
13
|
+
@matches.any? || @antimatches.any?
|
14
|
+
end
|
15
|
+
|
16
|
+
def build
|
17
|
+
return Stretchy::Queries::MatchAllQuery.new unless any?
|
18
|
+
|
19
|
+
if @matches.count > 1 || @antimatches.any?
|
20
|
+
bool_query
|
21
|
+
else
|
22
|
+
field, strings = @matches.first
|
23
|
+
Stretchy::Queries::MatchQuery.new(field: field, string: strings.join(' '))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def bool_query
|
28
|
+
Stretchy::Queries::BoolQuery.new(
|
29
|
+
must: to_queries(@matches),
|
30
|
+
must_not: to_queries(@antimatches)
|
31
|
+
)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def to_queries(matches)
|
37
|
+
matches.map do |field, strings|
|
38
|
+
Stretchy::Queries::MatchQuery.new(field: field, string: strings.join(' '))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module Stretchy
|
2
|
+
module Builders
|
3
|
+
class WhereBuilder
|
4
|
+
|
5
|
+
attr_accessor :terms, :antiterms, :exists, :empties,
|
6
|
+
:ranges, :antiranges, :geos, :antigeos
|
7
|
+
|
8
|
+
def initialize(options = {})
|
9
|
+
@terms = Hash.new { [] }
|
10
|
+
@antiterms = Hash.new { [] }
|
11
|
+
@ranges = {}
|
12
|
+
@antiranges = {}
|
13
|
+
@geos = {}
|
14
|
+
@antigeos = {}
|
15
|
+
|
16
|
+
@exists = []
|
17
|
+
@empties = []
|
18
|
+
end
|
19
|
+
|
20
|
+
def build
|
21
|
+
if use_bool?
|
22
|
+
bool_filter
|
23
|
+
elsif musts?
|
24
|
+
and_filter
|
25
|
+
elsif must_nots?
|
26
|
+
not_filter
|
27
|
+
else
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def musts?
|
33
|
+
@terms.any? || @exists.any? || @ranges.any? || @geos.any?
|
34
|
+
end
|
35
|
+
|
36
|
+
def must_nots?
|
37
|
+
@antiterms.any? || @empties.any? ||
|
38
|
+
@antiranges.any? || @antigeos.any?
|
39
|
+
end
|
40
|
+
|
41
|
+
def use_bool?
|
42
|
+
musts? && must_nots?
|
43
|
+
end
|
44
|
+
|
45
|
+
def any?
|
46
|
+
musts? || must_nots?
|
47
|
+
end
|
48
|
+
|
49
|
+
def bool_filter
|
50
|
+
Stretchy::Filters::BoolFilter.new(
|
51
|
+
must: build_filters(
|
52
|
+
terms: @terms,
|
53
|
+
exists: @exists,
|
54
|
+
ranges: @ranges,
|
55
|
+
geos: @geos
|
56
|
+
),
|
57
|
+
must_not: build_filters(
|
58
|
+
terms: @antiterms,
|
59
|
+
exists: @empties,
|
60
|
+
ranges: @antiranges,
|
61
|
+
geos: @antigeos
|
62
|
+
)
|
63
|
+
)
|
64
|
+
end
|
65
|
+
|
66
|
+
def and_filter
|
67
|
+
filter = nil
|
68
|
+
filters = build_filters(
|
69
|
+
terms: @terms,
|
70
|
+
exists: @exists,
|
71
|
+
ranges: @ranges,
|
72
|
+
geos: @geos
|
73
|
+
)
|
74
|
+
if filters.count > 1
|
75
|
+
filter = Stretchy::Filters::AndFilter.new(filters)
|
76
|
+
else
|
77
|
+
filter = filters.first
|
78
|
+
end
|
79
|
+
filter
|
80
|
+
end
|
81
|
+
|
82
|
+
def not_filter
|
83
|
+
filter = build_filters(
|
84
|
+
terms: @antiterms,
|
85
|
+
exists: @empties,
|
86
|
+
ranges: @antiranges,
|
87
|
+
geos: @antigeos
|
88
|
+
)
|
89
|
+
filter = Stretchy::Filters::AndFilter.new(filter) if filter.count > 1
|
90
|
+
Stretchy::Filters::NotFilter.new(filter)
|
91
|
+
end
|
92
|
+
|
93
|
+
def build_filters(options = {})
|
94
|
+
filters = []
|
95
|
+
terms = Hash(options[:terms])
|
96
|
+
ranges = Hash(options[:ranges])
|
97
|
+
geos = Hash(options[:geos])
|
98
|
+
exists = Array(options[:exists])
|
99
|
+
|
100
|
+
filters << Stretchy::Filters::TermsFilter.new(terms) if terms.any?
|
101
|
+
|
102
|
+
filters += exists.map do |field|
|
103
|
+
Stretchy::Filters::ExistsFilter.new(field)
|
104
|
+
end
|
105
|
+
|
106
|
+
filters += ranges.map do |field, values|
|
107
|
+
Stretchy::Filters::RangeFilter.new(
|
108
|
+
field: field,
|
109
|
+
min: values[:min],
|
110
|
+
max: values[:max]
|
111
|
+
)
|
112
|
+
end
|
113
|
+
|
114
|
+
filters += geos.map do |field, values|
|
115
|
+
Stretchy::Filters::GeoFilter.new(
|
116
|
+
field: field,
|
117
|
+
distance: values[:distance],
|
118
|
+
lat: values[:lat],
|
119
|
+
lng: values[:lng]
|
120
|
+
)
|
121
|
+
end
|
122
|
+
filters
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module Stretchy
|
2
|
+
module Clauses
|
3
|
+
class Base
|
4
|
+
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
DEFAULT_LIMIT = 30
|
8
|
+
DEFAULT_OFFSET = 0
|
9
|
+
|
10
|
+
attr_accessor :match_builder, :where_builder, :boost_builder,
|
11
|
+
:aggregate_builder, :inverse, :type, :index_name
|
12
|
+
|
13
|
+
alias :inverse? :inverse
|
14
|
+
|
15
|
+
delegate [:response, :results, :ids, :hits, :took, :shards, :total, :max_score] => :query_results
|
16
|
+
|
17
|
+
def initialize(base_or_opts = nil, options = {})
|
18
|
+
if base_or_opts && !base_or_opts.is_a?(Hash)
|
19
|
+
base = base_or_opts
|
20
|
+
@index_name = base.index_name
|
21
|
+
@type = base.type
|
22
|
+
@match_builder = base.match_builder
|
23
|
+
@where_builder = base.where_builder
|
24
|
+
@boost_builder = base.boost_builder
|
25
|
+
@aggregate_builder = base.aggregate_builder
|
26
|
+
@inverse = options[:inverse] || base.inverse
|
27
|
+
@limit = base.get_limit
|
28
|
+
@offset = base.get_offset
|
29
|
+
else
|
30
|
+
options = Hash(base_or_opts).merge(options)
|
31
|
+
@index_name = options[:index] || Stretchy.index_name
|
32
|
+
@type = options[:type]
|
33
|
+
@match_builder = Stretchy::Builders::MatchBuilder.new
|
34
|
+
@where_builder = Stretchy::Builders::WhereBuilder.new
|
35
|
+
@boost_builder = Stretchy::Builders::BoostBuilder.new
|
36
|
+
@aggregate_builder = nil
|
37
|
+
@inverse = options[:inverse]
|
38
|
+
@limit = DEFAULT_LIMIT
|
39
|
+
@offset = DEFAULT_OFFSET
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def limit(num)
|
44
|
+
@limit = num
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
def get_limit
|
49
|
+
@limit
|
50
|
+
end
|
51
|
+
|
52
|
+
def offset(num)
|
53
|
+
@offset = num
|
54
|
+
self
|
55
|
+
end
|
56
|
+
|
57
|
+
def get_offset
|
58
|
+
@offset
|
59
|
+
end
|
60
|
+
|
61
|
+
def match(options = {})
|
62
|
+
MatchClause.new(self, options)
|
63
|
+
end
|
64
|
+
|
65
|
+
def where(options = {})
|
66
|
+
WhereClause.new(self, options)
|
67
|
+
end
|
68
|
+
|
69
|
+
def boost(options = {})
|
70
|
+
BoostClause.new(self, options)
|
71
|
+
end
|
72
|
+
|
73
|
+
def to_search
|
74
|
+
return @to_search if @to_search
|
75
|
+
|
76
|
+
@to_search = if @where_builder.any?
|
77
|
+
Stretchy::Queries::FilteredQuery.new(
|
78
|
+
query: @match_builder.build,
|
79
|
+
filter: @where_builder.build
|
80
|
+
)
|
81
|
+
else
|
82
|
+
@match_builder.build
|
83
|
+
end
|
84
|
+
|
85
|
+
@to_search = @boost_builder.build(@to_search) if @boost_builder.any?
|
86
|
+
@to_search = @to_search.to_search
|
87
|
+
end
|
88
|
+
|
89
|
+
def query_results
|
90
|
+
@query_results ||= Stretchy::Results::Base.new(to_search.merge(from: @limit, size: @offset), type: @type)
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Stretchy
|
2
|
+
module Clauses
|
3
|
+
class BoostClause < Base
|
4
|
+
|
5
|
+
def initialize(base, options = {})
|
6
|
+
super(base)
|
7
|
+
@inverse = options.delete(:inverse)
|
8
|
+
end
|
9
|
+
|
10
|
+
def match(options = {})
|
11
|
+
BoostMatchClause.new(self, options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def where(options = {})
|
15
|
+
BoostWhereClause.new(self, options)
|
16
|
+
end
|
17
|
+
|
18
|
+
def random(*args)
|
19
|
+
@boost_builder.functions << Stretchy::Boosts::RandomBoost.new(*args)
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
def all(num)
|
24
|
+
@boost_builder.overall_boost = num
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
def max(num)
|
29
|
+
@boost_builder.max_boost = num
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
def score_mode(mode)
|
34
|
+
@boost_builder.score_mode = mode
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
def boost_mode(mode)
|
39
|
+
@boost_builder.boost_mode = mode
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
def not(options = {})
|
44
|
+
inst = self.class.new(self, options.merge(inverse: !inverse?))
|
45
|
+
inst
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Stretchy
|
2
|
+
module Clauses
|
3
|
+
class BoostMatchClause < BoostClause
|
4
|
+
|
5
|
+
def initialize(base, opts_or_string = {}, options = {})
|
6
|
+
super(base)
|
7
|
+
if opts_or_string.is_a?(Hash)
|
8
|
+
@inverse = opts_or_string.delete(:inverse) || options.delete(:inverse)
|
9
|
+
match_function(opts_or_string.merge(options))
|
10
|
+
else
|
11
|
+
@inverse = options.delete(:inverse)
|
12
|
+
match_function(options.merge('_all' => opts_or_string))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def not(opts_or_string = {}, options = {})
|
17
|
+
self.class.new(self, opts_or_string, options.merge(inverse: !inverse?))
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def match_function(options = {})
|
23
|
+
weight = options.delete(:weight)
|
24
|
+
clause = MatchClause.tmp(options)
|
25
|
+
boost = clause.to_boost(weight)
|
26
|
+
@boost_builder.functions << boost if boost
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Stretchy
|
2
|
+
module Clauses
|
3
|
+
class BoostWhereClause < BoostClause
|
4
|
+
|
5
|
+
def initialize(base, options = {})
|
6
|
+
super(base, options)
|
7
|
+
where_function(:init, options)
|
8
|
+
self
|
9
|
+
end
|
10
|
+
|
11
|
+
def range(*args)
|
12
|
+
where_function(:range, *args)
|
13
|
+
self
|
14
|
+
end
|
15
|
+
|
16
|
+
def geo(*args)
|
17
|
+
where_function(:geo, *args)
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def add_params(params = {})
|
24
|
+
where_function(:init, params)
|
25
|
+
end
|
26
|
+
|
27
|
+
def where_function(method, *args)
|
28
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
29
|
+
weight = options.delete(:weight)
|
30
|
+
|
31
|
+
clause = nil
|
32
|
+
if method == :init
|
33
|
+
clause = WhereClause.tmp(options.merge(inverse: inverse?))
|
34
|
+
else
|
35
|
+
args.push(options)
|
36
|
+
clause = WhereClause.tmp(inverse: inverse?).send(method, *args)
|
37
|
+
end
|
38
|
+
boost = clause.to_boost(weight)
|
39
|
+
|
40
|
+
@boost_builder.functions << boost if boost
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Stretchy
|
2
|
+
module Clauses
|
3
|
+
class MatchClause < Base
|
4
|
+
|
5
|
+
def self.tmp(options = {})
|
6
|
+
self.new(Base.new, options)
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(base, opts_or_str = {}, options = {})
|
10
|
+
super(base)
|
11
|
+
if opts_or_str.is_a?(Hash)
|
12
|
+
@inverse = opts_or_str.delete(:inverse) || options.delete(:inverse)
|
13
|
+
add_params(options.merge(opts_or_str))
|
14
|
+
else
|
15
|
+
@inverse = options.delete(:inverse)
|
16
|
+
add_params(options.merge('_all' => opts_or_str))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def not(opts_or_str = {}, options = {})
|
21
|
+
self.class.new(self, opts_or_str, options.merge(inverse: !@inverse))
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_boost(weight = nil)
|
25
|
+
weight ||= Stretchy::Boosts::FilterBoost::DEFAULT_WEIGHT
|
26
|
+
Stretchy::Boosts::FilterBoost.new(
|
27
|
+
filter: Stretchy::Filters::QueryFilter.new(
|
28
|
+
@match_builder.build
|
29
|
+
),
|
30
|
+
weight: weight
|
31
|
+
)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def add_params(params = {})
|
37
|
+
case params
|
38
|
+
when Hash
|
39
|
+
params.each do |field, params|
|
40
|
+
add_param(field, params)
|
41
|
+
end
|
42
|
+
else
|
43
|
+
add_param('_all', params)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def add_param(field, param)
|
48
|
+
if inverse?
|
49
|
+
@match_builder.antimatches[field] += Array(param)
|
50
|
+
else
|
51
|
+
@match_builder.matches[field] += Array(param)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module Stretchy
|
2
|
+
module Clauses
|
3
|
+
class WhereClause < Base
|
4
|
+
|
5
|
+
def self.tmp(options = {})
|
6
|
+
self.new(Base.new, options)
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(base, options = {})
|
10
|
+
super(base)
|
11
|
+
@inverse = options.delete(:inverse)
|
12
|
+
add_params(options)
|
13
|
+
end
|
14
|
+
|
15
|
+
def range(field, options = {})
|
16
|
+
min = max = nil
|
17
|
+
|
18
|
+
case options
|
19
|
+
when Hash
|
20
|
+
min = options[:min]
|
21
|
+
max = options[:max]
|
22
|
+
store = inverse? ? @where_builder.antiranges : @where_builder.ranges
|
23
|
+
store[field] = { min: min, max: max }
|
24
|
+
when Range
|
25
|
+
add_param(field, options)
|
26
|
+
end
|
27
|
+
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
def geo(field, options = {})
|
32
|
+
add_geo(field, options)
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
def not(options = {})
|
37
|
+
self.class.new(self, options.merge(inverse: !@inverse))
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_boost(weight = nil)
|
41
|
+
weight ||= Stretchy::Boosts::FilterBoost::DEFAULT_WEIGHT
|
42
|
+
|
43
|
+
if @match_builder.any? && @where_builder.any?
|
44
|
+
Stretchy::Boosts::FilterBoost.new(
|
45
|
+
filter: Stretchy::Filters::QueryFilter.new(
|
46
|
+
Stretchy::Queries::FilteredQuery.new(
|
47
|
+
query: @match_builder.build,
|
48
|
+
filter: @where_builder.build
|
49
|
+
)
|
50
|
+
),
|
51
|
+
weight: weight
|
52
|
+
)
|
53
|
+
|
54
|
+
elsif @match_builder.any?
|
55
|
+
Stretchy::Boosts::FilterBoost.new(
|
56
|
+
filter: Stretchy::Filters::QueryFilter.new(
|
57
|
+
@match_builder.build
|
58
|
+
),
|
59
|
+
weight: weight
|
60
|
+
)
|
61
|
+
|
62
|
+
elsif @where_builder.any?
|
63
|
+
Stretchy::Boosts::FilterBoost.new(
|
64
|
+
filter: @where_builder.build,
|
65
|
+
weight: weight
|
66
|
+
)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def add_params(options = {})
|
73
|
+
options.each do |field, param|
|
74
|
+
# if it is an array, process each param
|
75
|
+
# separately - ensures string & symbols
|
76
|
+
# always go into .match_builder
|
77
|
+
|
78
|
+
if param.is_a?(Array)
|
79
|
+
param.each{|p| add_param(field, p) }
|
80
|
+
else
|
81
|
+
add_param(field, param)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def add_geo(field, options = {})
|
87
|
+
store = inverse? ? @where_builder.antigeos : @where_builder.geos
|
88
|
+
store[field] = options
|
89
|
+
end
|
90
|
+
|
91
|
+
def add_param(field, param)
|
92
|
+
case param
|
93
|
+
when nil
|
94
|
+
store = inverse? ? @where_builder.exists : @where_builder.empties
|
95
|
+
store << field
|
96
|
+
when String, Symbol
|
97
|
+
if inverse?
|
98
|
+
@match_builder.antimatches[field] += Array(param)
|
99
|
+
else
|
100
|
+
@match_builder.matches[field] += Array(param)
|
101
|
+
end
|
102
|
+
when Range
|
103
|
+
store = inverse? ? @where_builder.antiranges : @where_builder.ranges
|
104
|
+
store[field] = { min: param.min, max: param.max }
|
105
|
+
else
|
106
|
+
store = inverse? ? @where_builder.antiterms : @where_builder.terms
|
107
|
+
store[field] += Array(param)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -4,8 +4,12 @@ module Stretchy
|
|
4
4
|
|
5
5
|
contract filters: {type: Stretchy::Filters::Base, array: true}
|
6
6
|
|
7
|
-
def initialize(
|
8
|
-
|
7
|
+
def initialize(*args)
|
8
|
+
if args.count == 1 && args.first.is_a?(Array)
|
9
|
+
@filters = args.first
|
10
|
+
else
|
11
|
+
@filters = args
|
12
|
+
end
|
9
13
|
validate!
|
10
14
|
end
|
11
15
|
|
@@ -6,18 +6,19 @@ module Stretchy
|
|
6
6
|
must_not: {type: Base, array: true},
|
7
7
|
should: {type: Base, array: true}
|
8
8
|
|
9
|
-
def initialize(
|
10
|
-
@must = Array(must)
|
11
|
-
@must_not = Array(must_not)
|
12
|
-
@should = Array(should)
|
9
|
+
def initialize(options = {})
|
10
|
+
@must = Array(options[:must])
|
11
|
+
@must_not = Array(options[:must_not])
|
12
|
+
@should = Array(options[:should])
|
13
13
|
validate!
|
14
|
+
require_one(must: @must, must_not: @must_not, should: @should)
|
14
15
|
end
|
15
16
|
|
16
17
|
def to_search
|
17
18
|
json = {}
|
18
|
-
json[:must] = @must.map(&:to_search) if @must
|
19
|
-
json[:must_not] = @must_not.map(&:to_search) if @must_not
|
20
|
-
json[:should] = @should.map(&:to_search) if @should
|
19
|
+
json[:must] = @must.map(&:to_search) if @must.any?
|
20
|
+
json[:must_not] = @must_not.map(&:to_search) if @must_not.any?
|
21
|
+
json[:should] = @should.map(&:to_search) if @should.any?
|
21
22
|
{ bool: json }
|
22
23
|
end
|
23
24
|
end
|