chewy 0.0.1 → 0.1.0
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 +13 -5
- data/.gitignore +1 -0
- data/.travis.yml +5 -3
- data/CHANGELOG.md +75 -0
- data/README.md +487 -92
- data/Rakefile +3 -2
- data/chewy.gemspec +2 -2
- data/filters +76 -0
- data/lib/chewy.rb +5 -3
- data/lib/chewy/config.rb +36 -19
- data/lib/chewy/fields/base.rb +5 -1
- data/lib/chewy/index.rb +22 -10
- data/lib/chewy/index/actions.rb +13 -13
- data/lib/chewy/index/search.rb +7 -2
- data/lib/chewy/query.rb +382 -64
- data/lib/chewy/query/context.rb +174 -0
- data/lib/chewy/query/criteria.rb +127 -34
- data/lib/chewy/query/loading.rb +9 -9
- data/lib/chewy/query/nodes/and.rb +25 -0
- data/lib/chewy/query/nodes/base.rb +17 -0
- data/lib/chewy/query/nodes/bool.rb +32 -0
- data/lib/chewy/query/nodes/equal.rb +34 -0
- data/lib/chewy/query/nodes/exists.rb +20 -0
- data/lib/chewy/query/nodes/expr.rb +28 -0
- data/lib/chewy/query/nodes/field.rb +106 -0
- data/lib/chewy/query/nodes/missing.rb +20 -0
- data/lib/chewy/query/nodes/not.rb +25 -0
- data/lib/chewy/query/nodes/or.rb +25 -0
- data/lib/chewy/query/nodes/prefix.rb +18 -0
- data/lib/chewy/query/nodes/query.rb +20 -0
- data/lib/chewy/query/nodes/range.rb +63 -0
- data/lib/chewy/query/nodes/raw.rb +15 -0
- data/lib/chewy/query/nodes/regexp.rb +31 -0
- data/lib/chewy/query/nodes/script.rb +20 -0
- data/lib/chewy/query/pagination.rb +28 -22
- data/lib/chewy/railtie.rb +23 -0
- data/lib/chewy/rspec/update_index.rb +20 -3
- data/lib/chewy/type/adapter/active_record.rb +78 -5
- data/lib/chewy/type/adapter/base.rb +46 -0
- data/lib/chewy/type/adapter/object.rb +40 -8
- data/lib/chewy/type/base.rb +1 -1
- data/lib/chewy/type/import.rb +18 -44
- data/lib/chewy/type/observe.rb +24 -14
- data/lib/chewy/version.rb +1 -1
- data/lib/tasks/chewy.rake +27 -0
- data/spec/chewy/config_spec.rb +30 -12
- data/spec/chewy/fields/base_spec.rb +11 -5
- data/spec/chewy/index/actions_spec.rb +20 -20
- data/spec/chewy/index/search_spec.rb +5 -5
- data/spec/chewy/index_spec.rb +28 -8
- data/spec/chewy/query/context_spec.rb +173 -0
- data/spec/chewy/query/criteria_spec.rb +219 -12
- data/spec/chewy/query/loading_spec.rb +6 -4
- data/spec/chewy/query/nodes/and_spec.rb +16 -0
- data/spec/chewy/query/nodes/bool_spec.rb +22 -0
- data/spec/chewy/query/nodes/equal_spec.rb +32 -0
- data/spec/chewy/query/nodes/exists_spec.rb +18 -0
- data/spec/chewy/query/nodes/missing_spec.rb +15 -0
- data/spec/chewy/query/nodes/not_spec.rb +16 -0
- data/spec/chewy/query/nodes/or_spec.rb +16 -0
- data/spec/chewy/query/nodes/prefix_spec.rb +16 -0
- data/spec/chewy/query/nodes/query_spec.rb +12 -0
- data/spec/chewy/query/nodes/range_spec.rb +32 -0
- data/spec/chewy/query/nodes/raw_spec.rb +11 -0
- data/spec/chewy/query/nodes/regexp_spec.rb +31 -0
- data/spec/chewy/query/nodes/script_spec.rb +15 -0
- data/spec/chewy/query/pagination_spec.rb +3 -2
- data/spec/chewy/query_spec.rb +83 -26
- data/spec/chewy/rspec/update_index_spec.rb +20 -0
- data/spec/chewy/type/adapter/active_record_spec.rb +102 -0
- data/spec/chewy/type/adapter/object_spec.rb +82 -0
- data/spec/chewy/type/import_spec.rb +30 -1
- data/spec/chewy/type/mapping_spec.rb +1 -1
- data/spec/chewy/type/observe_spec.rb +46 -12
- data/spec/spec_helper.rb +7 -6
- data/spec/support/class_helpers.rb +2 -2
- metadata +98 -48
- data/.rvmrc +0 -1
- data/lib/chewy/index/client.rb +0 -13
- data/spec/chewy/index/client_spec.rb +0 -18
@@ -0,0 +1,32 @@
|
|
1
|
+
module Chewy
|
2
|
+
class Query
|
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 = {
|
21
|
+
bool: Hash[METHODS.map do |method|
|
22
|
+
value = instance_variable_get("@#{method}")
|
23
|
+
[method.to_sym, value.map(&:__render__)] if value.any?
|
24
|
+
end.compact]
|
25
|
+
}
|
26
|
+
bool[:bool][:_cache] = !!@options[:cache] if @options.key?(:cache)
|
27
|
+
bool
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Chewy
|
2
|
+
class Query
|
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 Chewy
|
2
|
+
class Query
|
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: {term: @name}}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Chewy
|
2
|
+
class Query
|
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 Chewy
|
2
|
+
class Query
|
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,20 @@
|
|
1
|
+
module Chewy
|
2
|
+
class Query
|
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: {term: @name}.merge(@options.slice(:existence, :null_value))}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Chewy
|
2
|
+
class Query
|
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
|
+
if @options.key?(:cache)
|
17
|
+
{not: {filter: expr, _cache: !!@options[:cache]}}
|
18
|
+
else
|
19
|
+
{not: expr}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Chewy
|
2
|
+
class Query
|
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
|
+
if @options.key?(:cache)
|
17
|
+
{or: {filters: nodes, _cache: !!@options[:cache]}}
|
18
|
+
else
|
19
|
+
{or: nodes}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Chewy
|
2
|
+
class Query
|
3
|
+
module Nodes
|
4
|
+
class Prefix < Expr
|
5
|
+
def initialize name, value, options = {}
|
6
|
+
@name = name.to_s
|
7
|
+
@value, @options = value, options
|
8
|
+
end
|
9
|
+
|
10
|
+
def __render__
|
11
|
+
filter = {prefix: {@name => @value}}
|
12
|
+
filter[:prefix][:_cache] = !!@options[:cache] if @options.key?(:cache)
|
13
|
+
filter
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Chewy
|
2
|
+
class Query
|
3
|
+
module Nodes
|
4
|
+
class Query < Expr
|
5
|
+
def initialize query, options = {}
|
6
|
+
@query = query
|
7
|
+
@options = options
|
8
|
+
end
|
9
|
+
|
10
|
+
def __render__
|
11
|
+
if @options.key?(:cache)
|
12
|
+
{fquery: {query: @query, _cache: !!@options[:cache]}}
|
13
|
+
else
|
14
|
+
{query: @query}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Chewy
|
2
|
+
class Query
|
3
|
+
module Nodes
|
4
|
+
class Range < Expr
|
5
|
+
EXECUTION = {
|
6
|
+
:i => :index,
|
7
|
+
:index => :index,
|
8
|
+
:f => :fielddata,
|
9
|
+
:fielddata => :fielddata,
|
10
|
+
}
|
11
|
+
|
12
|
+
def initialize name, *args
|
13
|
+
@name = name.to_s
|
14
|
+
@options = args.extract_options!
|
15
|
+
@range = @options.extract!(:gt, :lt)
|
16
|
+
@bounds = @options.extract!(:left_closed, :right_closed)
|
17
|
+
execution = EXECUTION[args.first.to_sym] if args.first
|
18
|
+
@options[:execution] = execution if execution
|
19
|
+
end
|
20
|
+
|
21
|
+
def & other
|
22
|
+
if other.is_a?(self.class) && other.__name__ == @name
|
23
|
+
state = __state__.merge(other.__state__)
|
24
|
+
|
25
|
+
cache = other.__options__[:cache] || @options[:cache]
|
26
|
+
state[:cache] = cache unless cache.nil?
|
27
|
+
|
28
|
+
execution = other.__options__[:execution] || @options[:execution]
|
29
|
+
state[:execution] = execution unless execution.nil?
|
30
|
+
|
31
|
+
self.class.new(@name, state)
|
32
|
+
else
|
33
|
+
super
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def __name__
|
38
|
+
@name
|
39
|
+
end
|
40
|
+
|
41
|
+
def __state__
|
42
|
+
@range.merge(@bounds)
|
43
|
+
end
|
44
|
+
|
45
|
+
def __options__
|
46
|
+
@options
|
47
|
+
end
|
48
|
+
|
49
|
+
def __render__
|
50
|
+
body = {}
|
51
|
+
body[@bounds[:left_closed] ? :gte : :gt] = @range[:gt] if @range.key?(:gt)
|
52
|
+
body[@bounds[:right_closed] ? :lte : :lt] = @range[:lt] if @range.key?(:lt)
|
53
|
+
|
54
|
+
filter = {@name => body}
|
55
|
+
filter[:_cache] = !!@options[:cache] if @options.key?(:cache)
|
56
|
+
filter.merge!(@options.slice(:execution))
|
57
|
+
|
58
|
+
{range: filter}
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Chewy
|
2
|
+
class Query
|
3
|
+
module Nodes
|
4
|
+
class Regexp < Expr
|
5
|
+
FLAGS = %w(all anystring automaton complement empty intersection interval none)
|
6
|
+
|
7
|
+
def initialize name, regexp, *args
|
8
|
+
@name = name.to_s
|
9
|
+
@regexp = regexp.respond_to?(:source) ? regexp.source : regexp.to_s
|
10
|
+
@options = args.extract_options!
|
11
|
+
if args.any? || @options[:flags].present?
|
12
|
+
@options[:flags] = FLAGS & (args.any? ? args.flatten : @options[:flags]).map(&:to_s).map(&:downcase)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def __render__
|
17
|
+
body = @options[:flags] ?
|
18
|
+
{value: @regexp, flags: @options[:flags].map(&:to_s).map(&:upcase).uniq.join('|')} :
|
19
|
+
@regexp
|
20
|
+
filter = {@name => body}
|
21
|
+
if @options.key?(:cache)
|
22
|
+
filter[:_cache] = !!@options[:cache]
|
23
|
+
filter[:_cache_key] = @options[:cache].is_a?(TrueClass) || @options[:cache].is_a?(FalseClass) ?
|
24
|
+
@regexp.underscore : @options[:cache]
|
25
|
+
end
|
26
|
+
{regexp: filter}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|