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.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.rspec +3 -0
  4. data/Gemfile +6 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +37 -0
  7. data/Rakefile +2 -0
  8. data/chewy_query.gemspec +27 -0
  9. data/lib/chewy_query.rb +12 -0
  10. data/lib/chewy_query/builder.rb +865 -0
  11. data/lib/chewy_query/builder/compose.rb +64 -0
  12. data/lib/chewy_query/builder/criteria.rb +182 -0
  13. data/lib/chewy_query/builder/filters.rb +227 -0
  14. data/lib/chewy_query/builder/nodes/and.rb +26 -0
  15. data/lib/chewy_query/builder/nodes/base.rb +17 -0
  16. data/lib/chewy_query/builder/nodes/bool.rb +33 -0
  17. data/lib/chewy_query/builder/nodes/equal.rb +34 -0
  18. data/lib/chewy_query/builder/nodes/exists.rb +20 -0
  19. data/lib/chewy_query/builder/nodes/expr.rb +28 -0
  20. data/lib/chewy_query/builder/nodes/field.rb +106 -0
  21. data/lib/chewy_query/builder/nodes/has_child.rb +14 -0
  22. data/lib/chewy_query/builder/nodes/has_parent.rb +14 -0
  23. data/lib/chewy_query/builder/nodes/has_relation.rb +61 -0
  24. data/lib/chewy_query/builder/nodes/match_all.rb +11 -0
  25. data/lib/chewy_query/builder/nodes/missing.rb +20 -0
  26. data/lib/chewy_query/builder/nodes/not.rb +26 -0
  27. data/lib/chewy_query/builder/nodes/or.rb +26 -0
  28. data/lib/chewy_query/builder/nodes/prefix.rb +18 -0
  29. data/lib/chewy_query/builder/nodes/query.rb +20 -0
  30. data/lib/chewy_query/builder/nodes/range.rb +63 -0
  31. data/lib/chewy_query/builder/nodes/raw.rb +15 -0
  32. data/lib/chewy_query/builder/nodes/regexp.rb +33 -0
  33. data/lib/chewy_query/builder/nodes/script.rb +20 -0
  34. data/lib/chewy_query/version.rb +3 -0
  35. data/spec/chewy_query/builder/context_spec.rb +529 -0
  36. data/spec/chewy_query/builder/filters_spec.rb +181 -0
  37. data/spec/chewy_query/builder/nodes/and_spec.rb +16 -0
  38. data/spec/chewy_query/builder/nodes/bool_spec.rb +22 -0
  39. data/spec/chewy_query/builder/nodes/equal_spec.rb +58 -0
  40. data/spec/chewy_query/builder/nodes/exists_spec.rb +16 -0
  41. data/spec/chewy_query/builder/nodes/has_child_spec.rb +79 -0
  42. data/spec/chewy_query/builder/nodes/has_parent_spec.rb +84 -0
  43. data/spec/chewy_query/builder/nodes/match_all_spec.rb +11 -0
  44. data/spec/chewy_query/builder/nodes/missing_spec.rb +14 -0
  45. data/spec/chewy_query/builder/nodes/not_spec.rb +14 -0
  46. data/spec/chewy_query/builder/nodes/or_spec.rb +16 -0
  47. data/spec/chewy_query/builder/nodes/prefix_spec.rb +15 -0
  48. data/spec/chewy_query/builder/nodes/query_spec.rb +17 -0
  49. data/spec/chewy_query/builder/nodes/range_spec.rb +36 -0
  50. data/spec/chewy_query/builder/nodes/raw_spec.rb +11 -0
  51. data/spec/chewy_query/builder/nodes/regexp_spec.rb +45 -0
  52. data/spec/chewy_query/builder/nodes/script_spec.rb +16 -0
  53. data/spec/chewy_query/builder_spec.rb +196 -0
  54. data/spec/chewy_query_spec.rb +0 -0
  55. data/spec/spec_helper.rb +8 -0
  56. 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,14 @@
1
+ require 'chewy_query/builder/nodes/has_relation'
2
+
3
+ module ChewyQuery
4
+ class Builder
5
+ module Nodes
6
+ class HasChild < HasRelation
7
+ private
8
+ def _relation
9
+ :has_child
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ require 'chewy_query/builder/nodes/has_relation'
2
+
3
+ module ChewyQuery
4
+ class Builder
5
+ module Nodes
6
+ class HasParent < HasRelation
7
+ private
8
+ def _relation
9
+ :has_parent
10
+ end
11
+ end
12
+ end
13
+ end
14
+ 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,11 @@
1
+ module ChewyQuery
2
+ class Builder
3
+ module Nodes
4
+ class MatchAll < Expr
5
+ def __render__
6
+ { match_all: {} }
7
+ end
8
+ end
9
+ end
10
+ end
11
+ 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