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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 50cc4c9404f4fec945f7e1de80998603db979fe3
|
4
|
+
data.tar.gz: a4507b1b3aefe9a7924dcb487d248c4bac2de514
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0258c2c32f63a25f7e249b30b0dcf878263d3a78eea13b34dfed4b3bed4a835a9205edd954c0e4053cda2642d55618e2956f4ab6b6e96b695aafdd55639c58ff
|
7
|
+
data.tar.gz: 6c84d4f21a27d42e1439b49e24749ff1f4cecabaf4c32fb0ef734aaa813a073fa5faeaef220ec2d40d61cc8ee0e996e51ec853cca9f550967e80e6e2d0d7cd6c
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 undr
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# ChewyQuery
|
2
|
+
|
3
|
+
The query builder for ElasticSearch which was extracted from [chewy](https://github.com/toptal/chewy) gem.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'chewy_query'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
```
|
16
|
+
$ bundle
|
17
|
+
```
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
```
|
22
|
+
$ gem install chewy_query
|
23
|
+
```
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
See [chewy querying](https://github.com/toptal/chewy#index-querying).
|
28
|
+
|
29
|
+
Many thanks to @pyromaniac for his [chewy](https://github.com/toptal/chewy).
|
30
|
+
|
31
|
+
## Contributing
|
32
|
+
|
33
|
+
1. Fork it ( https://github.com/undr/chewy_query/fork )
|
34
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
35
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
36
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
37
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/chewy_query.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'chewy_query/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'chewy_query'
|
8
|
+
spec.version = ChewyQuery::VERSION
|
9
|
+
spec.authors = ['pyromaniac', 'undr']
|
10
|
+
spec.email = ['kinwizard@gmail.com', 'undr@yandex.ru']
|
11
|
+
spec.summary = %q{The query builder for ElasticSearch which was extracted from Chewy.}
|
12
|
+
spec.description = %q{The query builder for ElasticSearch which was extracted from Chewy.}
|
13
|
+
spec.homepage = ''
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_dependency 'activesupport', '>= 3.2'
|
22
|
+
|
23
|
+
spec.add_development_dependency 'bundler', '~> 1.6'
|
24
|
+
spec.add_development_dependency 'rake'
|
25
|
+
spec.add_development_dependency 'rspec'
|
26
|
+
spec.add_development_dependency 'its'
|
27
|
+
end
|
data/lib/chewy_query.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'active_support/core_ext'
|
3
|
+
require 'active_support/concern'
|
4
|
+
require 'active_support/json'
|
5
|
+
require 'i18n/core_ext/hash'
|
6
|
+
|
7
|
+
require "chewy_query/version"
|
8
|
+
require 'chewy_query/builder'
|
9
|
+
|
10
|
+
module ChewyQuery
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,865 @@
|
|
1
|
+
require 'chewy_query/builder/criteria'
|
2
|
+
require 'chewy_query/builder/filters'
|
3
|
+
|
4
|
+
module ChewyQuery
|
5
|
+
# Builder allows you to create ES search requests with convenient
|
6
|
+
# chainable DSL. Queries are lazy evaluated and might be merged.
|
7
|
+
#
|
8
|
+
# builder = ChewyQuery::Builder.new(:users, types: ['admin', 'manager', 'user'])
|
9
|
+
# builder.filter{ age < 42 }.query(text: {name: 'Alex'}).limit(20)
|
10
|
+
# builder = ChewyQuery::Builder.new(:users, types: 'admin')
|
11
|
+
# builder.filter{ age < 42 }.query(text: {name: 'Alex'}).limit(20)
|
12
|
+
#
|
13
|
+
class Builder
|
14
|
+
attr_reader :index, :options, :criteria
|
15
|
+
|
16
|
+
def initialize(index, options = {})
|
17
|
+
@index, @options = index, options
|
18
|
+
@types = Array.wrap(options.delete(:types))
|
19
|
+
@criteria = Criteria.new(options)
|
20
|
+
reset
|
21
|
+
end
|
22
|
+
|
23
|
+
# Comparation with other query or collection
|
24
|
+
# If other is collection - search request is executed and
|
25
|
+
# result is used for comparation
|
26
|
+
#
|
27
|
+
# builder.filter(term: {name: 'Johny'}) == builder.filter(term: {name: 'Johny'}) # => true
|
28
|
+
# builder.filter(term: {name: 'Johny'}) == builder.filter(term: {name: 'Johny'}).to_a # => true
|
29
|
+
# builder.filter(term: {name: 'Johny'}) == builder.filter(term: {name: 'Winnie'}) # => false
|
30
|
+
#
|
31
|
+
def ==(other)
|
32
|
+
super || if other.is_a?(self.class)
|
33
|
+
other.criteria == criteria
|
34
|
+
else
|
35
|
+
to_a == other
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Adds <tt>explain</tt> parameter to search request.
|
40
|
+
#
|
41
|
+
# builder.filter(term: {name: 'Johny'}).explain
|
42
|
+
# builder.filter(term: {name: 'Johny'}).explain(true)
|
43
|
+
# builder.filter(term: {name: 'Johny'}).explain(false)
|
44
|
+
#
|
45
|
+
# Calling explain without any arguments sets explanation flag to true.
|
46
|
+
#
|
47
|
+
# builder.filter(term: {name: 'Johny'}).explain
|
48
|
+
#
|
49
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-explain.html
|
50
|
+
#
|
51
|
+
def explain(value = nil)
|
52
|
+
chain{ criteria.update_request_options explain: (value.nil? ? true : value) }
|
53
|
+
end
|
54
|
+
|
55
|
+
# Adds <tt>version</tt> parameter to search request.
|
56
|
+
#
|
57
|
+
# builder.filter(term: {name: 'Johny'}).version
|
58
|
+
# builder.filter(term: {name: 'Johny'}).version(true)
|
59
|
+
# builder.filter(term: {name: 'Johny'}).version(false)
|
60
|
+
#
|
61
|
+
# Calling version without any arguments sets version flag to true.
|
62
|
+
#
|
63
|
+
# builder.filter(term: {name: 'Johny'}).version
|
64
|
+
#
|
65
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-version.html
|
66
|
+
#
|
67
|
+
def version(value = nil)
|
68
|
+
chain{ criteria.update_request_options version: (value.nil? ? true : value) }
|
69
|
+
end
|
70
|
+
|
71
|
+
# Sets query compilation mode for search request.
|
72
|
+
# Not used if only one filter for search is specified.
|
73
|
+
# Possible values:
|
74
|
+
#
|
75
|
+
# * <tt>:must</tt>
|
76
|
+
# Default value. Query compiles into a bool <tt>must</tt> query.
|
77
|
+
#
|
78
|
+
# Ex:
|
79
|
+
#
|
80
|
+
# builder.query(text: {name: 'Johny'}).query(range: {age: {lte: 42}})
|
81
|
+
# # => {body: {
|
82
|
+
# query: {bool: {must: [{text: {name: 'Johny'}}, {range: {age: {lte: 42}}}]}}
|
83
|
+
# }}
|
84
|
+
#
|
85
|
+
# * <tt>:should</tt>
|
86
|
+
# Query compiles into a bool <tt>should</tt> query.
|
87
|
+
#
|
88
|
+
# Ex:
|
89
|
+
#
|
90
|
+
# builder.query(text: {name: 'Johny'}).query(range: {age: {lte: 42}}).query_mode(:should)
|
91
|
+
# # => {body: {
|
92
|
+
# query: {bool: {should: [{text: {name: 'Johny'}}, {range: {age: {lte: 42}}}]}}
|
93
|
+
# }}
|
94
|
+
#
|
95
|
+
# * Any acceptable <tt>minimum_should_match</tt> value (1, '2', '75%')
|
96
|
+
# Query compiles into a bool <tt>should</tt> query with <tt>minimum_should_match</tt> set.
|
97
|
+
#
|
98
|
+
# Ex:
|
99
|
+
#
|
100
|
+
# builder.query(text: {name: 'Johny'}).query(range: {age: {lte: 42}}).query_mode('50%')
|
101
|
+
# # => {body: {
|
102
|
+
# query: {bool: {
|
103
|
+
# should: [{text: {name: 'Johny'}}, {range: {age: {lte: 42}}}],
|
104
|
+
# minimum_should_match: '50%'
|
105
|
+
# }}
|
106
|
+
# }}
|
107
|
+
#
|
108
|
+
# * <tt>:dis_max</tt>
|
109
|
+
# Query compiles into a <tt>dis_max</tt> query.
|
110
|
+
#
|
111
|
+
# Ex:
|
112
|
+
#
|
113
|
+
# builder.query(text: {name: 'Johny'}).query(range: {age: {lte: 42}}).query_mode(:dis_max)
|
114
|
+
# # => {body: {
|
115
|
+
# query: {dis_max: {queries: [{text: {name: 'Johny'}}, {range: {age: {lte: 42}}}]}}
|
116
|
+
# }}
|
117
|
+
#
|
118
|
+
# * Any Float value (0.0, 0.7, 1.0)
|
119
|
+
# Query compiles into a <tt>dis_max</tt> query with <tt>tie_breaker</tt> option set.
|
120
|
+
#
|
121
|
+
# Ex:
|
122
|
+
#
|
123
|
+
# builder.query(text: {name: 'Johny'}).query(range: {age: {lte: 42}}).query_mode(0.7)
|
124
|
+
# # => {body: {
|
125
|
+
# query: {dis_max: {
|
126
|
+
# queries: [{text: {name: 'Johny'}}, {range: {age: {lte: 42}}}],
|
127
|
+
# tie_breaker: 0.7
|
128
|
+
# }}
|
129
|
+
# }}
|
130
|
+
#
|
131
|
+
# Default value for <tt>:query_mode</tt> might be changed
|
132
|
+
# with <tt>ChewyQuery.query_mode</tt> config option.
|
133
|
+
#
|
134
|
+
# ChewyQuery.query_mode = :dis_max
|
135
|
+
# ChewyQuery.query_mode = '50%'
|
136
|
+
#
|
137
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-dis-max-query.html
|
138
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html
|
139
|
+
#
|
140
|
+
def query_mode(value)
|
141
|
+
chain{ criteria.update_options query_mode: value }
|
142
|
+
end
|
143
|
+
|
144
|
+
# Sets query compilation mode for search request.
|
145
|
+
# Not used if only one filter for search is specified.
|
146
|
+
# Possible values:
|
147
|
+
#
|
148
|
+
# * <tt>:and</tt>
|
149
|
+
# Default value. Filter compiles into an <tt>and</tt> filter.
|
150
|
+
#
|
151
|
+
# Ex:
|
152
|
+
#
|
153
|
+
# builder.filter{ name == 'Johny' }.filter{ age <= 42 }
|
154
|
+
# # => {body: {query: {filtered: {
|
155
|
+
# query: {...},
|
156
|
+
# filter: {and: [{term: {name: 'Johny'}}, {range: {age: {lte: 42}}}]}
|
157
|
+
# }}}}
|
158
|
+
#
|
159
|
+
# * <tt>:or</tt>
|
160
|
+
# Filter compiles into an <tt>or</tt> filter.
|
161
|
+
#
|
162
|
+
# Ex:
|
163
|
+
#
|
164
|
+
# builder.filter{ name == 'Johny' }.filter{ age <= 42 }.filter_mode(:or)
|
165
|
+
# # => {body: {query: {filtered: {
|
166
|
+
# query: {...},
|
167
|
+
# filter: {or: [{term: {name: 'Johny'}}, {range: {age: {lte: 42}}}]}
|
168
|
+
# }}}}
|
169
|
+
#
|
170
|
+
# * <tt>:must</tt>
|
171
|
+
# Filter compiles into a bool <tt>must</tt> filter.
|
172
|
+
#
|
173
|
+
# Ex:
|
174
|
+
#
|
175
|
+
# builder.filter{ name == 'Johny' }.filter{ age <= 42 }.filter_mode(:must)
|
176
|
+
# # => {body: {query: {filtered: {
|
177
|
+
# query: {...},
|
178
|
+
# filter: {bool: {must: [{term: {name: 'Johny'}}, {range: {age: {lte: 42}}}]}}
|
179
|
+
# }}}}
|
180
|
+
#
|
181
|
+
# * <tt>:should</tt>
|
182
|
+
# Filter compiles into a bool <tt>should</tt> filter.
|
183
|
+
#
|
184
|
+
# Ex:
|
185
|
+
#
|
186
|
+
# builder.filter{ name == 'Johny' }.filter{ age <= 42 }.filter_mode(:should)
|
187
|
+
# # => {body: {query: {filtered: {
|
188
|
+
# query: {...},
|
189
|
+
# filter: {bool: {should: [{term: {name: 'Johny'}}, {range: {age: {lte: 42}}}]}}
|
190
|
+
# }}}}
|
191
|
+
#
|
192
|
+
# * Any acceptable <tt>minimum_should_match</tt> value (1, '2', '75%')
|
193
|
+
# Filter compiles into bool <tt>should</tt> filter with <tt>minimum_should_match</tt> set.
|
194
|
+
#
|
195
|
+
# Ex:
|
196
|
+
#
|
197
|
+
# builder.filter{ name == 'Johny' }.filter{ age <= 42 }.filter_mode('50%')
|
198
|
+
# # => {body: {query: {filtered: {
|
199
|
+
# query: {...},
|
200
|
+
# filter: {bool: {
|
201
|
+
# should: [{term: {name: 'Johny'}}, {range: {age: {lte: 42}}}],
|
202
|
+
# minimum_should_match: '50%'
|
203
|
+
# }}
|
204
|
+
# }}}}
|
205
|
+
#
|
206
|
+
# Default value for <tt>:filter_mode</tt> might be changed
|
207
|
+
# with <tt>ChewyQuery.filter_mode</tt> config option.
|
208
|
+
#
|
209
|
+
# ChewyQuery.filter_mode = :should
|
210
|
+
# ChewyQuery.filter_mode = '50%'
|
211
|
+
#
|
212
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-and-filter.html
|
213
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-bool-filter.html
|
214
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-or-filter.html
|
215
|
+
#
|
216
|
+
def filter_mode(value)
|
217
|
+
chain{ criteria.update_options filter_mode: value }
|
218
|
+
end
|
219
|
+
|
220
|
+
# Acts the same way as `filter_mode`, but used for `post_filter`.
|
221
|
+
# Note that it fallbacks by default to `ChewyQuery.filter_mode` if
|
222
|
+
# `ChewyQuery.post_filter_mode` is nil.
|
223
|
+
#
|
224
|
+
# builder.post_filter{ name == 'Johny' }.post_filter{ age <= 42 }.post_filter_mode(:and)
|
225
|
+
# builder.post_filter{ name == 'Johny' }.post_filter{ age <= 42 }.post_filter_mode(:should)
|
226
|
+
# builder.post_filter{ name == 'Johny' }.post_filter{ age <= 42 }.post_filter_mode('50%')
|
227
|
+
#
|
228
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-and-filter.html
|
229
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-bool-filter.html
|
230
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-or-filter.html
|
231
|
+
#
|
232
|
+
def post_filter_mode(value)
|
233
|
+
chain{ criteria.update_options post_filter_mode: value }
|
234
|
+
end
|
235
|
+
|
236
|
+
# Sets elasticsearch <tt>size</tt> search request param
|
237
|
+
# Default value is set in the elasticsearch and is 10.
|
238
|
+
#
|
239
|
+
# builder.filter{ name == 'Johny' }.limit(100)
|
240
|
+
# # => {body: {
|
241
|
+
# query: {...},
|
242
|
+
# size: 100
|
243
|
+
# }}
|
244
|
+
#
|
245
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-from-size.html
|
246
|
+
#
|
247
|
+
def limit(value)
|
248
|
+
chain{ criteria.update_request_options size: Integer(value) }
|
249
|
+
end
|
250
|
+
|
251
|
+
# Sets elasticsearch <tt>from</tt> search request param
|
252
|
+
#
|
253
|
+
# builder.filter{ name == 'Johny' }.offset(300)
|
254
|
+
# # => {body: {
|
255
|
+
# query: {...},
|
256
|
+
# from: 300
|
257
|
+
# }}
|
258
|
+
#
|
259
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-from-size.html
|
260
|
+
#
|
261
|
+
def offset(value)
|
262
|
+
chain{ criteria.update_request_options from: Integer(value) }
|
263
|
+
end
|
264
|
+
|
265
|
+
# Elasticsearch highlight query option support
|
266
|
+
#
|
267
|
+
# builder.query(...).highlight(fields: { ... })
|
268
|
+
#
|
269
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-highlighting.html
|
270
|
+
#
|
271
|
+
def highlight(value)
|
272
|
+
chain{ criteria.update_request_options highlight: value }
|
273
|
+
end
|
274
|
+
|
275
|
+
# Elasticsearch rescore query option support
|
276
|
+
#
|
277
|
+
# builder.query(...).rescore(query: { ... })
|
278
|
+
#
|
279
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-rescore.html
|
280
|
+
#
|
281
|
+
def rescore(value)
|
282
|
+
chain{ criteria.update_request_options(rescore: value) }
|
283
|
+
end
|
284
|
+
|
285
|
+
# Adds facets section to the search request.
|
286
|
+
# All the chained facets a merged and added to the
|
287
|
+
# search request
|
288
|
+
#
|
289
|
+
# builder.facets(tags: {terms: {field: 'tags'}}).facets(ages: {terms: {field: 'age'}})
|
290
|
+
# # => {body: {
|
291
|
+
# query: {...},
|
292
|
+
# facets: {tags: {terms: {field: 'tags'}}, ages: {terms: {field: 'age'}}}
|
293
|
+
# }}
|
294
|
+
#
|
295
|
+
# If called parameterless - returns result facets from ES performing request.
|
296
|
+
# Returns empty hash if no facets was requested or resulted.
|
297
|
+
#
|
298
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-facets.html
|
299
|
+
#
|
300
|
+
def facets(params)
|
301
|
+
chain{ criteria.update_facets(params) }
|
302
|
+
end
|
303
|
+
|
304
|
+
# Adds a script function to score the search request. All scores are
|
305
|
+
# added to the search request and combinded according to
|
306
|
+
# <tt>boost_mode</tt> and <tt>score_mode</tt>
|
307
|
+
#
|
308
|
+
# builder.script_score("doc['boost'].value", filter: { term: {foo: :bar} })
|
309
|
+
# # => {body:
|
310
|
+
# query: {
|
311
|
+
# function_score: {
|
312
|
+
# query: { ...},
|
313
|
+
# functions: [{
|
314
|
+
# script_score: {
|
315
|
+
# script: "doc['boost'].value"
|
316
|
+
# },
|
317
|
+
# filter: { term: { foo: :bar } }
|
318
|
+
# }
|
319
|
+
# }]
|
320
|
+
# } } }
|
321
|
+
#
|
322
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html#_script_score
|
323
|
+
#
|
324
|
+
def script_score(script, options = {})
|
325
|
+
scoring = options.merge(script_score: { script: script })
|
326
|
+
chain{ criteria.update_scores(scoring) }
|
327
|
+
end
|
328
|
+
|
329
|
+
# Adds a boost factor to the search request. All scores are
|
330
|
+
# added to the search request and combinded according to
|
331
|
+
# <tt>boost_mode</tt> and <tt>score_mode</tt>
|
332
|
+
#
|
333
|
+
# This probably only makes sense if you specifiy a filter
|
334
|
+
# for the boost factor as well
|
335
|
+
#
|
336
|
+
# builder.boost_factor(23, filter: { term: { foo: :bar} })
|
337
|
+
# # => {body:
|
338
|
+
# query: {
|
339
|
+
# function_score: {
|
340
|
+
# query: { ...},
|
341
|
+
# functions: [{
|
342
|
+
# boost_factor: 23,
|
343
|
+
# filter: { term: { foo: :bar } }
|
344
|
+
# }]
|
345
|
+
# } } }
|
346
|
+
#
|
347
|
+
# @see
|
348
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html#_boost_factor
|
349
|
+
#
|
350
|
+
def boost_factor(factor, options = {})
|
351
|
+
scoring = options.merge(boost_factor: factor.to_i)
|
352
|
+
chain{ criteria.update_scores(scoring) }
|
353
|
+
end
|
354
|
+
|
355
|
+
# Adds a random score to the search request. All scores are
|
356
|
+
# added to the search request and combinded according to
|
357
|
+
# <tt>boost_mode</tt> and <tt>score_mode</tt>
|
358
|
+
#
|
359
|
+
# This probably only makes sense if you specifiy a filter
|
360
|
+
# for the random score as well.
|
361
|
+
#
|
362
|
+
# If you do not pass in a seed value, Time.now will be used
|
363
|
+
#
|
364
|
+
# builder.random_score(23, filter: { foo: :bar})
|
365
|
+
# # => {body:
|
366
|
+
# query: {
|
367
|
+
# function_score: {
|
368
|
+
# query: { ...},
|
369
|
+
# functions: [{
|
370
|
+
# random_score: { seed: 23 },
|
371
|
+
# filter: { foo: :bar }
|
372
|
+
# }]
|
373
|
+
# } } }
|
374
|
+
#
|
375
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html#_random
|
376
|
+
#
|
377
|
+
def random_score(seed = Time.now, options = {})
|
378
|
+
scoring = options.merge(random_score: { seed: seed.to_i })
|
379
|
+
chain{ criteria.update_scores(scoring) }
|
380
|
+
end
|
381
|
+
|
382
|
+
# Add a field value scoring to the search. All scores are
|
383
|
+
# added to the search request and combinded according to
|
384
|
+
# <tt>boost_mode</tt> and <tt>score_mode</tt>
|
385
|
+
#
|
386
|
+
# This function is only available in Elasticsearch 1.2 and
|
387
|
+
# greater
|
388
|
+
#
|
389
|
+
# builder.field_value_factor(
|
390
|
+
# {
|
391
|
+
# field: :boost,
|
392
|
+
# factor: 1.2,
|
393
|
+
# modifier: :sqrt
|
394
|
+
# }, filter: { foo: :bar})
|
395
|
+
# # => {body:
|
396
|
+
# query: {
|
397
|
+
# function_score: {
|
398
|
+
# query: { ...},
|
399
|
+
# functions: [{
|
400
|
+
# field_value_factor: {
|
401
|
+
# field: :boost,
|
402
|
+
# factor: 1.2,
|
403
|
+
# modifier: :sqrt
|
404
|
+
# },
|
405
|
+
# filter: { foo: :bar }
|
406
|
+
# }]
|
407
|
+
# } } }
|
408
|
+
#
|
409
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html#_field_value_factor
|
410
|
+
#
|
411
|
+
def field_value_factor(settings, options = {})
|
412
|
+
scoring = options.merge(field_value_factor: settings)
|
413
|
+
chain{ criteria.update_scores(scoring) }
|
414
|
+
end
|
415
|
+
|
416
|
+
# Add a decay scoring to the search. All scores are
|
417
|
+
# added to the search request and combinded according to
|
418
|
+
# <tt>boost_mode</tt> and <tt>score_mode</tt>
|
419
|
+
#
|
420
|
+
# The parameters have default values, but those may not
|
421
|
+
# be very useful for most applications.
|
422
|
+
#
|
423
|
+
# builder.decay(
|
424
|
+
# :gauss,
|
425
|
+
# :field,
|
426
|
+
# origin: '11, 12',
|
427
|
+
# scale: '2km',
|
428
|
+
# offset: '5km'
|
429
|
+
# decay: 0.4
|
430
|
+
# filter: { foo: :bar})
|
431
|
+
# # => {body:
|
432
|
+
# query: {
|
433
|
+
# gauss: {
|
434
|
+
# query: { ...},
|
435
|
+
# functions: [{
|
436
|
+
# gauss: {
|
437
|
+
# field: {
|
438
|
+
# origin: '11, 12',
|
439
|
+
# scale: '2km',
|
440
|
+
# offset: '5km',
|
441
|
+
# decay: 0.4
|
442
|
+
# }
|
443
|
+
# },
|
444
|
+
# filter: { foo: :bar }
|
445
|
+
# }]
|
446
|
+
# } } }
|
447
|
+
#
|
448
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html#_decay_functions
|
449
|
+
#
|
450
|
+
def decay(function, field, options = {})
|
451
|
+
field_options = {
|
452
|
+
origin: options.delete(:origin) || 0,
|
453
|
+
scale: options.delete(:scale) || 1,
|
454
|
+
offset: options.delete(:offset) || 0,
|
455
|
+
decay: options.delete(:decay) || 0.1
|
456
|
+
}
|
457
|
+
scoring = options.merge(function => {
|
458
|
+
field => field_options
|
459
|
+
})
|
460
|
+
chain{ criteria.update_scores(scoring) }
|
461
|
+
end
|
462
|
+
|
463
|
+
# Sets elasticsearch <tt>aggregations</tt> search request param
|
464
|
+
#
|
465
|
+
# builder.filter{ name == 'Johny' }.aggregations(category_id: {terms: {field: 'category_ids'}})
|
466
|
+
# # => {body: {
|
467
|
+
# query: {...},
|
468
|
+
# aggregations: {
|
469
|
+
# terms: {
|
470
|
+
# field: 'category_ids'
|
471
|
+
# }
|
472
|
+
# }
|
473
|
+
# }}
|
474
|
+
#
|
475
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-aggregations.html
|
476
|
+
#
|
477
|
+
def aggregations(params = nil)
|
478
|
+
chain{ criteria.update_aggregations params }
|
479
|
+
end
|
480
|
+
alias :aggs :aggregations
|
481
|
+
|
482
|
+
# Sets elasticsearch <tt>suggest</tt> search request param
|
483
|
+
#
|
484
|
+
# builder.suggest(name: {text: 'Joh', term: {field: 'name'}})
|
485
|
+
# # => {body: {
|
486
|
+
# query: {...},
|
487
|
+
# suggest: {
|
488
|
+
# text: 'Joh',
|
489
|
+
# term: {
|
490
|
+
# field: 'name'
|
491
|
+
# }
|
492
|
+
# }
|
493
|
+
# }}
|
494
|
+
#
|
495
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-suggesters.html
|
496
|
+
#
|
497
|
+
def suggest(params = nil)
|
498
|
+
chain{ criteria.update_suggest params }
|
499
|
+
end
|
500
|
+
|
501
|
+
# Marks the criteria as having zero records. This scope always returns empty array
|
502
|
+
# without touching the elasticsearch server.
|
503
|
+
# All the chained calls of methods don't affect the result
|
504
|
+
#
|
505
|
+
# UsersIndex.none.to_a
|
506
|
+
# # => []
|
507
|
+
# UsersIndex.query(text: {name: 'Johny'}).none.to_a
|
508
|
+
# # => []
|
509
|
+
# UsersIndex.none.query(text: {name: 'Johny'}).to_a
|
510
|
+
# # => []
|
511
|
+
def none
|
512
|
+
chain{ criteria.update_options(none: true) }
|
513
|
+
end
|
514
|
+
|
515
|
+
# Setups strategy for top-level filtered query
|
516
|
+
#
|
517
|
+
# builder.filter { name == 'Johny'}.strategy(:leap_frog)
|
518
|
+
# # => {body: {
|
519
|
+
# query: { filtered: {
|
520
|
+
# filter: { term: { name: 'Johny' } },
|
521
|
+
# strategy: 'leap_frog'
|
522
|
+
# } }
|
523
|
+
# }}
|
524
|
+
#
|
525
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-filtered-query.html#_filter_strategy
|
526
|
+
#
|
527
|
+
def strategy(value = nil)
|
528
|
+
chain{ criteria.update_options(strategy: value) }
|
529
|
+
end
|
530
|
+
|
531
|
+
# Adds one or more query to the search request
|
532
|
+
# Internally queries are stored as an array
|
533
|
+
# While the full query compilation this array compiles
|
534
|
+
# according to <tt>:query_mode</tt> option value
|
535
|
+
#
|
536
|
+
# By default it joines inside <tt>must</tt> query
|
537
|
+
# See <tt>#query_mode</tt> chainable method for more info.
|
538
|
+
#
|
539
|
+
# builder.query(match: {name: 'Johny'}).query(range: {age: {lte: 42}})
|
540
|
+
# # => {body: {
|
541
|
+
# query: {bool: {must: [{match: {name: 'Johny'}}, {range: {age: {lte: 42}}}]}}
|
542
|
+
# }}
|
543
|
+
#
|
544
|
+
# If only one query was specified, it will become a result
|
545
|
+
# query as is, without joining.
|
546
|
+
#
|
547
|
+
# builder.query(match: {name: 'Johny'})
|
548
|
+
# # => {body: {
|
549
|
+
# query: {match: {name: 'Johny'}}
|
550
|
+
# }}
|
551
|
+
#
|
552
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-queries.html
|
553
|
+
#
|
554
|
+
def query(params)
|
555
|
+
chain{ criteria.update_queries(params) }
|
556
|
+
end
|
557
|
+
|
558
|
+
# Adds one or more filter to the search request
|
559
|
+
# Internally filters are stored as an array
|
560
|
+
# While the full query compilation this array compiles
|
561
|
+
# according to <tt>:filter_mode</tt> option value
|
562
|
+
#
|
563
|
+
# By default it joins inside <tt>and</tt> filter
|
564
|
+
# See <tt>#filter_mode</tt> chainable method for more info.
|
565
|
+
#
|
566
|
+
# Also this method supports block DSL.
|
567
|
+
# See <tt>ChewyQuery::Builder::Filters</tt> for more info.
|
568
|
+
#
|
569
|
+
# builder.filter(term: {name: 'Johny'}).filter(range: {age: {lte: 42}})
|
570
|
+
# builder.filter{ name == 'Johny' }.filter{ age <= 42 }
|
571
|
+
# # => {body: {query: {filtered: {
|
572
|
+
# query: {...},
|
573
|
+
# filter: {and: [{term: {name: 'Johny'}}, {range: {age: {lte: 42}}}]}
|
574
|
+
# }}}}
|
575
|
+
#
|
576
|
+
# If only one filter was specified, it will become a result
|
577
|
+
# filter as is, without joining.
|
578
|
+
#
|
579
|
+
# builder.filter(term: {name: 'Johny'})
|
580
|
+
# # => {body: {query: {filtered: {
|
581
|
+
# query: {...},
|
582
|
+
# filter: {term: {name: 'Johny'}}
|
583
|
+
# }}}}
|
584
|
+
#
|
585
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-filters.html
|
586
|
+
#
|
587
|
+
def filter(params = nil, &block)
|
588
|
+
params = Filters.new(&block).__render__ if block
|
589
|
+
chain{ criteria.update_filters(params) }
|
590
|
+
end
|
591
|
+
|
592
|
+
# Adds one or more post_filter to the search request
|
593
|
+
# Internally post_filters are stored as an array
|
594
|
+
# While the full query compilation this array compiles
|
595
|
+
# according to <tt>:post_filter_mode</tt> option value
|
596
|
+
#
|
597
|
+
# By default it joins inside <tt>and</tt> filter
|
598
|
+
# See <tt>#post_filter_mode</tt> chainable method for more info.
|
599
|
+
#
|
600
|
+
# Also this method supports block DSL.
|
601
|
+
# See <tt>ChewyQuery::Builder::Filters</tt> for more info.
|
602
|
+
#
|
603
|
+
# builder.post_filter(term: {name: 'Johny'}).post_filter(range: {age: {lte: 42}})
|
604
|
+
# builder.post_filter{ name == 'Johny' }.post_filter{ age <= 42 }
|
605
|
+
# # => {body: {
|
606
|
+
# post_filter: {and: [{term: {name: 'Johny'}}, {range: {age: {lte: 42}}}]}
|
607
|
+
# }}
|
608
|
+
#
|
609
|
+
# If only one post_filter was specified, it will become a result
|
610
|
+
# post_filter as is, without joining.
|
611
|
+
#
|
612
|
+
# builder.post_filter(term: {name: 'Johny'})
|
613
|
+
# # => {body: {
|
614
|
+
# post_filter: {term: {name: 'Johny'}}
|
615
|
+
# }}
|
616
|
+
#
|
617
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-post-filter.html
|
618
|
+
#
|
619
|
+
def post_filter(params = nil, &block)
|
620
|
+
params = Filters.new(&block).__render__ if block
|
621
|
+
chain{ criteria.update_post_filters(params) }
|
622
|
+
end
|
623
|
+
|
624
|
+
# Sets the boost mode for custom scoring/boosting.
|
625
|
+
# Not used if no score functions are specified
|
626
|
+
# Possible values:
|
627
|
+
#
|
628
|
+
# * <tt>:multiply</tt>
|
629
|
+
# Default value. Query score and function result are multiplied.
|
630
|
+
#
|
631
|
+
# Ex:
|
632
|
+
#
|
633
|
+
# builder.boost_mode('multiply').script_score('doc['boost'].value')
|
634
|
+
# # => {body: {query: function_score: {
|
635
|
+
# query: {...},
|
636
|
+
# boost_mode: 'multiply',
|
637
|
+
# functions: [ ... ]
|
638
|
+
# }}}
|
639
|
+
#
|
640
|
+
# * <tt>:replace</tt>
|
641
|
+
# Only function result is used, query score is ignored.
|
642
|
+
#
|
643
|
+
# * <tt>:sum</tt>
|
644
|
+
# Query score and function score are added.
|
645
|
+
#
|
646
|
+
# * <tt>:avg</tt>
|
647
|
+
# Average of query and function score.
|
648
|
+
#
|
649
|
+
# * <tt>:max</tt>
|
650
|
+
# Max of query and function score.
|
651
|
+
#
|
652
|
+
# * <tt>:min</tt>
|
653
|
+
# Min of query and function score.
|
654
|
+
#
|
655
|
+
# Default value for <tt>:boost_mode</tt> might be changed
|
656
|
+
# with <tt>ChewyQuery.score_mode</tt> config option.
|
657
|
+
#
|
658
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html
|
659
|
+
#
|
660
|
+
def boost_mode(value)
|
661
|
+
chain{ criteria.update_options(boost_mode: value) }
|
662
|
+
end
|
663
|
+
|
664
|
+
# Sets the scoring mode for combining function scores/boosts
|
665
|
+
# Not used if no score functions are specified.
|
666
|
+
# Possible values:
|
667
|
+
#
|
668
|
+
# * <tt>:multiply</tt>
|
669
|
+
# Default value. Scores are multiplied.
|
670
|
+
#
|
671
|
+
# Ex:
|
672
|
+
#
|
673
|
+
# builder.score_mode('multiply').script_score('doc['boost'].value')
|
674
|
+
# # => {body: {query: function_score: {
|
675
|
+
# query: {...},
|
676
|
+
# score_mode: 'multiply',
|
677
|
+
# functions: [ ... ]
|
678
|
+
# }}}
|
679
|
+
#
|
680
|
+
# * <tt>:sum</tt>
|
681
|
+
# Scores are summed.
|
682
|
+
#
|
683
|
+
# * <tt>:avg</tt>
|
684
|
+
# Scores are averaged.
|
685
|
+
#
|
686
|
+
# * <tt>:first</tt>
|
687
|
+
# The first function that has a matching filter is applied.
|
688
|
+
#
|
689
|
+
# * <tt>:max</tt>
|
690
|
+
# Maximum score is used.
|
691
|
+
#
|
692
|
+
# * <tt>:min</tt>
|
693
|
+
# Minimum score is used
|
694
|
+
#
|
695
|
+
# Default value for <tt>:score_mode</tt> might be changed
|
696
|
+
# with <tt>ChewyQuery.score_mode</tt> config option.
|
697
|
+
#
|
698
|
+
# ChewyQuery.score_mode = :first
|
699
|
+
#
|
700
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html
|
701
|
+
#
|
702
|
+
def score_mode(value)
|
703
|
+
chain{ criteria.update_options(score_mode: value) }
|
704
|
+
end
|
705
|
+
|
706
|
+
# Sets search request sorting
|
707
|
+
#
|
708
|
+
# builder.order(:first_name, :last_name).order(age: :desc).order(price: {order: :asc, mode: :avg})
|
709
|
+
# # => {body: {
|
710
|
+
# query: {...},
|
711
|
+
# sort: ['first_name', 'last_name', {age: 'desc'}, {price: {order: 'asc', mode: 'avg'}}]
|
712
|
+
# }}
|
713
|
+
#
|
714
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-sort.html
|
715
|
+
#
|
716
|
+
def order(*params)
|
717
|
+
chain{ criteria.update_sort(params) }
|
718
|
+
end
|
719
|
+
|
720
|
+
# Cleans up previous search sorting and sets the new one
|
721
|
+
#
|
722
|
+
# builder.order(:first_name, :last_name).order(age: :desc).reorder(price: {order: :asc, mode: :avg})
|
723
|
+
# # => {body: {
|
724
|
+
# query: {...},
|
725
|
+
# sort: [{price: {order: 'asc', mode: 'avg'}}]
|
726
|
+
# }}
|
727
|
+
#
|
728
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-sort.html
|
729
|
+
#
|
730
|
+
def reorder(*params)
|
731
|
+
chain{ criteria.update_sort(params, purge: true) }
|
732
|
+
end
|
733
|
+
|
734
|
+
# Sets search request field list
|
735
|
+
#
|
736
|
+
# builder.only(:first_name, :last_name).only(:age)
|
737
|
+
# # => {body: {
|
738
|
+
# query: {...},
|
739
|
+
# fields: ['first_name', 'last_name', 'age']
|
740
|
+
# }}
|
741
|
+
#
|
742
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-fields.html
|
743
|
+
#
|
744
|
+
def only(*params)
|
745
|
+
chain{ criteria.update_fields(params) }
|
746
|
+
end
|
747
|
+
|
748
|
+
# Cleans up previous search field list and sets the new one
|
749
|
+
#
|
750
|
+
# builder.only(:first_name, :last_name).only!(:age)
|
751
|
+
# # => {body: {
|
752
|
+
# query: {...},
|
753
|
+
# fields: ['age']
|
754
|
+
# }}
|
755
|
+
#
|
756
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-fields.html
|
757
|
+
#
|
758
|
+
def only!(*params)
|
759
|
+
chain{ criteria.update_fields(params, purge: true) }
|
760
|
+
end
|
761
|
+
|
762
|
+
# Specify types participating in the search result
|
763
|
+
# Works via <tt>types</tt> filter. Always merged with another filters
|
764
|
+
# with the <tt>and</tt> filter.
|
765
|
+
#
|
766
|
+
# builder.types(:admin, :manager).filters{ name == 'Johny' }.filters{ age <= 42 }
|
767
|
+
# # => {body: {query: {filtered: {
|
768
|
+
# query: {...},
|
769
|
+
# filter: {and: [
|
770
|
+
# {or: [
|
771
|
+
# {type: {value: 'admin'}},
|
772
|
+
# {type: {value: 'manager'}}
|
773
|
+
# ]},
|
774
|
+
# {term: {name: 'Johny'}},
|
775
|
+
# {range: {age: {lte: 42}}}
|
776
|
+
# ]}
|
777
|
+
# }}}}
|
778
|
+
#
|
779
|
+
# builder.types(:admin, :manager).filters{ name == 'Johny' }.filters{ age <= 42 }.filter_mode(:or)
|
780
|
+
# # => {body: {query: {filtered: {
|
781
|
+
# query: {...},
|
782
|
+
# filter: {and: [
|
783
|
+
# {or: [
|
784
|
+
# {type: {value: 'admin'}},
|
785
|
+
# {type: {value: 'manager'}}
|
786
|
+
# ]},
|
787
|
+
# {or: [
|
788
|
+
# {term: {name: 'Johny'}},
|
789
|
+
# {range: {age: {lte: 42}}}
|
790
|
+
# ]}
|
791
|
+
# ]}
|
792
|
+
# }}}}
|
793
|
+
#
|
794
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-type-filter.html
|
795
|
+
#
|
796
|
+
def types(*params)
|
797
|
+
if params.any?
|
798
|
+
chain{ criteria.update_types(params) }
|
799
|
+
else
|
800
|
+
@types
|
801
|
+
end
|
802
|
+
end
|
803
|
+
|
804
|
+
# Acts the same way as <tt>types</tt>, but cleans up previously set types
|
805
|
+
#
|
806
|
+
# builder.types(:admin).types!(:manager)
|
807
|
+
# # => {body: {query: {filtered: {
|
808
|
+
# query: {...},
|
809
|
+
# filter: {type: {value: 'manager'}}
|
810
|
+
# }}}}
|
811
|
+
#
|
812
|
+
# @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-type-filter.html
|
813
|
+
#
|
814
|
+
def types!(*params)
|
815
|
+
chain{ criteria.update_types(params, purge: true) }
|
816
|
+
end
|
817
|
+
|
818
|
+
# Merges two queries.
|
819
|
+
# Merges all the values in criteria with the same rules as values added manually.
|
820
|
+
#
|
821
|
+
# scope1 = builder.filter{ name == 'Johny' }
|
822
|
+
# scope2 = builder.filter{ age <= 42 }
|
823
|
+
# scope3 = builder.filter{ name == 'Johny' }.filter{ age <= 42 }
|
824
|
+
#
|
825
|
+
# scope1.merge(scope2) == scope3 # => true
|
826
|
+
#
|
827
|
+
def merge(other)
|
828
|
+
chain{ criteria.merge!(other.criteria) }
|
829
|
+
end
|
830
|
+
|
831
|
+
def delete_all_request
|
832
|
+
@delete_all_request ||= criteria.delete_all_request_body.merge(index: index_name, type: types)
|
833
|
+
end
|
834
|
+
|
835
|
+
|
836
|
+
def request
|
837
|
+
@request ||= criteria.request_body.merge(index: index_name, type: types)
|
838
|
+
end
|
839
|
+
|
840
|
+
def inspect
|
841
|
+
"#<%s:%#016x @request=%s>" % [self.class, (object_id << 1), request]
|
842
|
+
end
|
843
|
+
|
844
|
+
protected
|
845
|
+
|
846
|
+
def reset
|
847
|
+
@request, @delete_all_request = nil
|
848
|
+
end
|
849
|
+
|
850
|
+
def initialize_clone(other)
|
851
|
+
@criteria = other.criteria.clone
|
852
|
+
reset
|
853
|
+
end
|
854
|
+
|
855
|
+
private
|
856
|
+
|
857
|
+
def index_name
|
858
|
+
index.respond_to?(:index_name) ? index.index_name : index
|
859
|
+
end
|
860
|
+
|
861
|
+
def chain(&block)
|
862
|
+
clone.tap{|q| q.instance_eval(&block) }
|
863
|
+
end
|
864
|
+
end
|
865
|
+
end
|