chewy_query 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.rspec +3 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +37 -0
- data/Rakefile +2 -0
- data/chewy_query.gemspec +27 -0
- data/lib/chewy_query.rb +12 -0
- data/lib/chewy_query/builder.rb +865 -0
- data/lib/chewy_query/builder/compose.rb +64 -0
- data/lib/chewy_query/builder/criteria.rb +182 -0
- data/lib/chewy_query/builder/filters.rb +227 -0
- data/lib/chewy_query/builder/nodes/and.rb +26 -0
- data/lib/chewy_query/builder/nodes/base.rb +17 -0
- data/lib/chewy_query/builder/nodes/bool.rb +33 -0
- data/lib/chewy_query/builder/nodes/equal.rb +34 -0
- data/lib/chewy_query/builder/nodes/exists.rb +20 -0
- data/lib/chewy_query/builder/nodes/expr.rb +28 -0
- data/lib/chewy_query/builder/nodes/field.rb +106 -0
- data/lib/chewy_query/builder/nodes/has_child.rb +14 -0
- data/lib/chewy_query/builder/nodes/has_parent.rb +14 -0
- data/lib/chewy_query/builder/nodes/has_relation.rb +61 -0
- data/lib/chewy_query/builder/nodes/match_all.rb +11 -0
- data/lib/chewy_query/builder/nodes/missing.rb +20 -0
- data/lib/chewy_query/builder/nodes/not.rb +26 -0
- data/lib/chewy_query/builder/nodes/or.rb +26 -0
- data/lib/chewy_query/builder/nodes/prefix.rb +18 -0
- data/lib/chewy_query/builder/nodes/query.rb +20 -0
- data/lib/chewy_query/builder/nodes/range.rb +63 -0
- data/lib/chewy_query/builder/nodes/raw.rb +15 -0
- data/lib/chewy_query/builder/nodes/regexp.rb +33 -0
- data/lib/chewy_query/builder/nodes/script.rb +20 -0
- data/lib/chewy_query/version.rb +3 -0
- data/spec/chewy_query/builder/context_spec.rb +529 -0
- data/spec/chewy_query/builder/filters_spec.rb +181 -0
- data/spec/chewy_query/builder/nodes/and_spec.rb +16 -0
- data/spec/chewy_query/builder/nodes/bool_spec.rb +22 -0
- data/spec/chewy_query/builder/nodes/equal_spec.rb +58 -0
- data/spec/chewy_query/builder/nodes/exists_spec.rb +16 -0
- data/spec/chewy_query/builder/nodes/has_child_spec.rb +79 -0
- data/spec/chewy_query/builder/nodes/has_parent_spec.rb +84 -0
- data/spec/chewy_query/builder/nodes/match_all_spec.rb +11 -0
- data/spec/chewy_query/builder/nodes/missing_spec.rb +14 -0
- data/spec/chewy_query/builder/nodes/not_spec.rb +14 -0
- data/spec/chewy_query/builder/nodes/or_spec.rb +16 -0
- data/spec/chewy_query/builder/nodes/prefix_spec.rb +15 -0
- data/spec/chewy_query/builder/nodes/query_spec.rb +17 -0
- data/spec/chewy_query/builder/nodes/range_spec.rb +36 -0
- data/spec/chewy_query/builder/nodes/raw_spec.rb +11 -0
- data/spec/chewy_query/builder/nodes/regexp_spec.rb +45 -0
- data/spec/chewy_query/builder/nodes/script_spec.rb +16 -0
- data/spec/chewy_query/builder_spec.rb +196 -0
- data/spec/chewy_query_spec.rb +0 -0
- data/spec/spec_helper.rb +8 -0
- metadata +191 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
module ChewyQuery
|
2
|
+
class Builder
|
3
|
+
module Nodes
|
4
|
+
class And < Expr
|
5
|
+
def initialize(*nodes)
|
6
|
+
@options = nodes.extract_options!
|
7
|
+
@nodes = nodes.flatten.map{|node| node.is_a?(self.class) ? node.__nodes__ : node }.flatten
|
8
|
+
end
|
9
|
+
|
10
|
+
def __nodes__
|
11
|
+
@nodes
|
12
|
+
end
|
13
|
+
|
14
|
+
def __render__
|
15
|
+
nodes = @nodes.map(&:__render__)
|
16
|
+
|
17
|
+
if @options.key?(:cache)
|
18
|
+
{ and: { filters: nodes, _cache: !!@options[:cache] } }
|
19
|
+
else
|
20
|
+
{ and: nodes }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ChewyQuery
|
2
|
+
class Builder
|
3
|
+
module Nodes
|
4
|
+
class Base
|
5
|
+
def render
|
6
|
+
raise NotImplementedError
|
7
|
+
end
|
8
|
+
|
9
|
+
def eql?(other)
|
10
|
+
other.is_a?(self.class) && instance_variables.all? do |ivar|
|
11
|
+
instance_variable_get(ivar).eql? other.instance_variable_get(ivar)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module ChewyQuery
|
2
|
+
class Builder
|
3
|
+
module Nodes
|
4
|
+
class Bool < Expr
|
5
|
+
METHODS = %w(must must_not should)
|
6
|
+
|
7
|
+
def initialize(options = {})
|
8
|
+
@options = options
|
9
|
+
@must, @must_not, @should = [], [], []
|
10
|
+
end
|
11
|
+
|
12
|
+
METHODS.each do |method|
|
13
|
+
define_method method do |*exprs|
|
14
|
+
instance_variable_get("@#{method}").push(*exprs)
|
15
|
+
self
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def __render__
|
20
|
+
bool = METHODS.map do |method|
|
21
|
+
value = instance_variable_get("@#{method}")
|
22
|
+
[method.to_sym, value.map(&:__render__)] if value.any?
|
23
|
+
end.compact
|
24
|
+
|
25
|
+
bool = { bool: Hash[bool] }
|
26
|
+
|
27
|
+
bool[:bool][:_cache] = !!@options[:cache] if @options.key?(:cache)
|
28
|
+
bool
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module ChewyQuery
|
2
|
+
class Builder
|
3
|
+
module Nodes
|
4
|
+
class Equal < Expr
|
5
|
+
EXECUTION = {
|
6
|
+
:| => :or,
|
7
|
+
:or => :or,
|
8
|
+
:& => :and,
|
9
|
+
:and => :and,
|
10
|
+
:b => :bool,
|
11
|
+
:bool => :bool,
|
12
|
+
:f => :fielddata,
|
13
|
+
:fielddata => :fielddata,
|
14
|
+
}
|
15
|
+
|
16
|
+
def initialize(name, value, *args)
|
17
|
+
@name = name.to_s
|
18
|
+
@value = value
|
19
|
+
@options = args.extract_options!
|
20
|
+
execution = EXECUTION[args.first.to_sym] if args.first
|
21
|
+
@options[:execution] = execution if execution
|
22
|
+
end
|
23
|
+
|
24
|
+
def __render__
|
25
|
+
filter = (@value.is_a?(Array) ? :terms : :term)
|
26
|
+
body = { @name => @value }
|
27
|
+
body.merge!(@options.slice(:execution)) if filter == :terms
|
28
|
+
body.merge!(_cache: !!@options[:cache]) if @options.key?(:cache)
|
29
|
+
{ filter => body }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module ChewyQuery
|
2
|
+
class Builder
|
3
|
+
module Nodes
|
4
|
+
class Exists < Expr
|
5
|
+
def initialize(name, options = {})
|
6
|
+
@name = name.to_s
|
7
|
+
@options = options
|
8
|
+
end
|
9
|
+
|
10
|
+
def !
|
11
|
+
Nodes::Missing.new(@name, null_value: true)
|
12
|
+
end
|
13
|
+
|
14
|
+
def __render__
|
15
|
+
{ exists: { field: @name } }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module ChewyQuery
|
2
|
+
class Builder
|
3
|
+
module Nodes
|
4
|
+
class Expr < Base
|
5
|
+
def &(other)
|
6
|
+
Nodes::And.new(self, other)
|
7
|
+
end
|
8
|
+
|
9
|
+
def |(other)
|
10
|
+
Nodes::Or.new(self, other)
|
11
|
+
end
|
12
|
+
|
13
|
+
def !
|
14
|
+
Nodes::Not.new(self)
|
15
|
+
end
|
16
|
+
|
17
|
+
def ~
|
18
|
+
@options[:cache] = true
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def __render__
|
23
|
+
raise NotImplementedError
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module ChewyQuery
|
2
|
+
class Builder
|
3
|
+
module Nodes
|
4
|
+
class Field < Base
|
5
|
+
def initialize(name, *args)
|
6
|
+
@name = name.to_s
|
7
|
+
@args = args
|
8
|
+
end
|
9
|
+
|
10
|
+
def !
|
11
|
+
Nodes::Missing.new(@name)
|
12
|
+
end
|
13
|
+
|
14
|
+
def ~
|
15
|
+
__options_merge__!(cache: true)
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
def >(value)
|
20
|
+
Nodes::Range.new(@name, *__options_merge__(gt: value))
|
21
|
+
end
|
22
|
+
|
23
|
+
def <(value)
|
24
|
+
Nodes::Range.new(@name, *__options_merge__(lt: value))
|
25
|
+
end
|
26
|
+
|
27
|
+
def >=(value)
|
28
|
+
Nodes::Range.new(@name, *__options_merge__(gt: value, left_closed: true))
|
29
|
+
end
|
30
|
+
|
31
|
+
def <=(value)
|
32
|
+
Nodes::Range.new(@name, *__options_merge__(lt: value, right_closed: true))
|
33
|
+
end
|
34
|
+
|
35
|
+
def ==(value)
|
36
|
+
case value
|
37
|
+
when nil
|
38
|
+
Nodes::Missing.new(@name, existence: false, null_value: true)
|
39
|
+
when ::Regexp
|
40
|
+
Nodes::Regexp.new(@name, value, *@args)
|
41
|
+
when ::Range
|
42
|
+
Nodes::Range.new(@name, *__options_merge__(gt: value.first, lt: value.last))
|
43
|
+
else
|
44
|
+
if value.is_a?(Array) && value.first.is_a?(::Range)
|
45
|
+
Nodes::Range.new(@name, *__options_merge__(
|
46
|
+
gt: value.first.first, lt: value.first.last,
|
47
|
+
left_closed: true, right_closed: true
|
48
|
+
))
|
49
|
+
else
|
50
|
+
Nodes::Equal.new(@name, value, *@args)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def !=(value)
|
56
|
+
case value
|
57
|
+
when nil
|
58
|
+
Nodes::Exists.new(@name)
|
59
|
+
else
|
60
|
+
Nodes::Not.new(self == value)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def =~(value)
|
65
|
+
case value
|
66
|
+
when ::Regexp
|
67
|
+
Nodes::Regexp.new(@name, value, *@args)
|
68
|
+
else
|
69
|
+
Nodes::Prefix.new(@name, value, @args.extract_options!)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def !~(value)
|
74
|
+
Not.new(self =~ value)
|
75
|
+
end
|
76
|
+
|
77
|
+
def method_missing(method, *args, &block)
|
78
|
+
method = method.to_s
|
79
|
+
if method =~ /\?\Z/
|
80
|
+
Nodes::Exists.new([@name, method.gsub(/\?\Z/, '')].join(?.))
|
81
|
+
else
|
82
|
+
self.class.new([@name, method].join(?.), *args)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def to_ary
|
87
|
+
nil
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def __options_merge__!(additional = {})
|
93
|
+
options = @args.extract_options!
|
94
|
+
options = options.merge(additional)
|
95
|
+
@args.push(options)
|
96
|
+
end
|
97
|
+
|
98
|
+
def __options_merge__(additional = {})
|
99
|
+
options = @args.extract_options!
|
100
|
+
options = options.merge(additional)
|
101
|
+
@args + [options]
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'chewy_query/builder/compose'
|
2
|
+
|
3
|
+
module ChewyQuery
|
4
|
+
class Builder
|
5
|
+
module Nodes
|
6
|
+
class HasRelation < Expr
|
7
|
+
include Compose
|
8
|
+
|
9
|
+
def initialize(type, outer = nil)
|
10
|
+
@type = type.to_s
|
11
|
+
@outer = outer
|
12
|
+
@query_mode = :must
|
13
|
+
@filter_mode = :and
|
14
|
+
@queries = []
|
15
|
+
@filters = []
|
16
|
+
end
|
17
|
+
|
18
|
+
def query_mode(mode)
|
19
|
+
@query_mode = mode
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
def filter_mode(mode)
|
24
|
+
@filter_mode = mode
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
def query(params = nil, &block)
|
29
|
+
if block
|
30
|
+
raise 'Query DLS is not supported yet'
|
31
|
+
else
|
32
|
+
@queries.push(params)
|
33
|
+
end
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
def filter(params = nil, &block)
|
38
|
+
if block
|
39
|
+
@filters.push(ChewyQuery::Builder::Filters.new(@outer, &block).__render__)
|
40
|
+
else
|
41
|
+
@filters.push(params)
|
42
|
+
end
|
43
|
+
self
|
44
|
+
end
|
45
|
+
|
46
|
+
def __render__
|
47
|
+
queries = _queries_join(@queries, @query_mode)
|
48
|
+
filters = _filters_join(@filters, @filter_mode)
|
49
|
+
|
50
|
+
body = if filters && !queries
|
51
|
+
{ filter: filters }
|
52
|
+
else
|
53
|
+
_filtered_query(queries, filters)
|
54
|
+
end || {}
|
55
|
+
|
56
|
+
{ _relation => body.merge(type: @type) } if body
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module ChewyQuery
|
2
|
+
class Builder
|
3
|
+
module Nodes
|
4
|
+
class Missing < Expr
|
5
|
+
def initialize(name, options = {})
|
6
|
+
@name = name.to_s
|
7
|
+
@options = options.reverse_merge(existence: true, null_value: false)
|
8
|
+
end
|
9
|
+
|
10
|
+
def !
|
11
|
+
Nodes::Exists.new(@name)
|
12
|
+
end
|
13
|
+
|
14
|
+
def __render__
|
15
|
+
{ missing: { field: @name }.merge(@options.slice(:existence, :null_value)) }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module ChewyQuery
|
2
|
+
class Builder
|
3
|
+
module Nodes
|
4
|
+
class Not < Expr
|
5
|
+
def initialize(expr, options = {})
|
6
|
+
@expr = expr
|
7
|
+
@options = options
|
8
|
+
end
|
9
|
+
|
10
|
+
def !
|
11
|
+
@expr
|
12
|
+
end
|
13
|
+
|
14
|
+
def __render__
|
15
|
+
expr = @expr.__render__
|
16
|
+
|
17
|
+
if @options.key?(:cache)
|
18
|
+
{ not: { filter: expr, _cache: !!@options[:cache] } }
|
19
|
+
else
|
20
|
+
{ not: expr }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module ChewyQuery
|
2
|
+
class Builder
|
3
|
+
module Nodes
|
4
|
+
class Or < Expr
|
5
|
+
def initialize(*nodes)
|
6
|
+
@options = nodes.extract_options!
|
7
|
+
@nodes = nodes.flatten.map{|node| node.is_a?(self.class) ? node.__nodes__ : node }.flatten
|
8
|
+
end
|
9
|
+
|
10
|
+
def __nodes__
|
11
|
+
@nodes
|
12
|
+
end
|
13
|
+
|
14
|
+
def __render__
|
15
|
+
nodes = @nodes.map(&:__render__)
|
16
|
+
|
17
|
+
if @options.key?(:cache)
|
18
|
+
{ or: { filters: nodes, _cache: !!@options[:cache] } }
|
19
|
+
else
|
20
|
+
{ or: nodes }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|