class ChewyQuery::Builder
Builder
allows you to create ES search requests with convenient chainable DSL. Queries are lazy evaluated and might be merged.
builder = ChewyQuery::Builder.new(:users, types: ['admin', 'manager', 'user']) builder.filter{ age < 42 }.query(text: {name: 'Alex'}).limit(20) builder = ChewyQuery::Builder.new(:users, types: 'admin') builder.filter{ age < 42 }.query(text: {name: 'Alex'}).limit(20)
Attributes
Public Class Methods
# File lib/chewy_query/builder.rb, line 16 def initialize(index, options = {}) @index, @options = index, options @types = Array.wrap(options.delete(:types)) @criteria = Criteria.new(options) reset end
Public Instance Methods
Comparation with other query or collection If other is collection - search request is executed and result is used for comparation
builder.filter(term: {name: 'Johny'}) == builder.filter(term: {name: 'Johny'}) # => true builder.filter(term: {name: 'Johny'}) == builder.filter(term: {name: 'Johny'}).to_a # => true builder.filter(term: {name: 'Johny'}) == builder.filter(term: {name: 'Winnie'}) # => false
# File lib/chewy_query/builder.rb, line 31 def ==(other) super || if other.is_a?(self.class) other.criteria == criteria else to_a == other end end
Sets elasticsearch aggregations
search request param
builder.filter{ name == 'Johny' }.aggregations(category_id: {terms: {field: 'category_ids'}}) # => {body: { query: {...}, aggregations: { terms: { field: 'category_ids' } } }}
@see www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-aggregations.html
# File lib/chewy_query/builder.rb, line 477 def aggregations(params = nil) chain{ criteria.update_aggregations params } end
Adds a boost factor to the search request. All scores are added to the search request and combinded according to boost_mode
and score_mode
This probably only makes sense if you specifiy a filter for the boost factor as well
builder.boost_factor(23, filter: { term: { foo: :bar} }) # => {body: query: { function_score: { query: { ...}, functions: [{ boost_factor: 23, filter: { term: { foo: :bar } } }] } } }
# File lib/chewy_query/builder.rb, line 350 def boost_factor(factor, options = {}) scoring = options.merge(boost_factor: factor.to_i) chain{ criteria.update_scores(scoring) } end
Sets the boost mode for custom scoring/boosting. Not used if no score functions are specified Possible values:
-
:multiply
Default value. Query score and function result are multiplied.Ex:
builder.boost_mode('multiply').script_score('doc['boost'].value') # => {body: {query: function_score: { query: {...}, boost_mode: 'multiply', functions: [ ... ] }}}
-
:replace
Only function result is used, query score is ignored. -
:sum
Query score and function score are added. -
:avg
Average of query and function score. -
:max
Max of query and function score. -
:min
Min of query and function score.
Default value for :boost_mode
might be changed with ChewyQuery.score_mode
config option.
@see www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html
# File lib/chewy_query/builder.rb, line 660 def boost_mode(value) chain{ criteria.update_options(boost_mode: value) } end
Add a decay scoring to the search. All scores are added to the search request and combinded according to boost_mode
and score_mode
The parameters have default values, but those may not be very useful for most applications.
builder.decay( :gauss, :field, origin: '11, 12', scale: '2km', offset: '5km' decay: 0.4 filter: { foo: :bar}) # => {body: query: { gauss: { query: { ...}, functions: [{ gauss: { field: { origin: '11, 12', scale: '2km', offset: '5km', decay: 0.4 } }, filter: { foo: :bar } }] } } }
# File lib/chewy_query/builder.rb, line 450 def decay(function, field, options = {}) field_options = { origin: options.delete(:origin) || 0, scale: options.delete(:scale) || 1, offset: options.delete(:offset) || 0, decay: options.delete(:decay) || 0.1 } scoring = options.merge(function => { field => field_options }) chain{ criteria.update_scores(scoring) } end
# File lib/chewy_query/builder.rb, line 831 def delete_all_request @delete_all_request ||= criteria.delete_all_request_body.merge(index: index_name, type: types) end
Adds explain
parameter to search request.
builder.filter(term: {name: 'Johny'}).explain builder.filter(term: {name: 'Johny'}).explain(true) builder.filter(term: {name: 'Johny'}).explain(false)
Calling explain without any arguments sets explanation flag to true.
builder.filter(term: {name: 'Johny'}).explain
@see www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-explain.html
# File lib/chewy_query/builder.rb, line 51 def explain(value = nil) chain{ criteria.update_request_options explain: (value.nil? ? true : value) } end
Adds facets section to the search request. All the chained facets a merged and added to the search request
builder.facets(tags: {terms: {field: 'tags'}}).facets(ages: {terms: {field: 'age'}}) # => {body: { query: {...}, facets: {tags: {terms: {field: 'tags'}}, ages: {terms: {field: 'age'}}} }}
If called parameterless - returns result facets from ES performing request. Returns empty hash if no facets was requested or resulted.
@see www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-facets.html
# File lib/chewy_query/builder.rb, line 300 def facets(params) chain{ criteria.update_facets(params) } end
Add a field value scoring to the search. All scores are added to the search request and combinded according to boost_mode
and score_mode
This function is only available in Elasticsearch 1.2 and greater
builder.field_value_factor( { field: :boost, factor: 1.2, modifier: :sqrt }, filter: { foo: :bar}) # => {body: query: { function_score: { query: { ...}, functions: [{ field_value_factor: { field: :boost, factor: 1.2, modifier: :sqrt }, filter: { foo: :bar } }] } } }
# File lib/chewy_query/builder.rb, line 411 def field_value_factor(settings, options = {}) scoring = options.merge(field_value_factor: settings) chain{ criteria.update_scores(scoring) } end
Adds one or more filter to the search request Internally filters are stored as an array While the full query compilation this array compiles according to :filter_mode
option value
By default it joins inside and
filter See #filter_mode
chainable method for more info.
Also this method supports block DSL. See ChewyQuery::Builder::Filters
for more info.
builder.filter(term: {name: 'Johny'}).filter(range: {age: {lte: 42}}) builder.filter{ name == 'Johny' }.filter{ age <= 42 } # => {body: {query: {filtered: { query: {...}, filter: {and: [{term: {name: 'Johny'}}, {range: {age: {lte: 42}}}]} }}}}
If only one filter was specified, it will become a result filter as is, without joining.
builder.filter(term: {name: 'Johny'}) # => {body: {query: {filtered: { query: {...}, filter: {term: {name: 'Johny'}} }}}}
@see www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-filters.html
# File lib/chewy_query/builder.rb, line 587 def filter(params = nil, &block) params = Filters.new(&block).__render__ if block chain{ criteria.update_filters(params) } end
Sets query compilation mode for search request. Not used if only one filter for search is specified. Possible values:
-
:and
Default value. Filter compiles into anand
filter.Ex:
builder.filter{ name == 'Johny' }.filter{ age <= 42 } # => {body: {query: {filtered: { query: {...}, filter: {and: [{term: {name: 'Johny'}}, {range: {age: {lte: 42}}}]} }}}}
-
:or
Filter compiles into anor
filter.Ex:
builder.filter{ name == 'Johny' }.filter{ age <= 42 }.filter_mode(:or) # => {body: {query: {filtered: { query: {...}, filter: {or: [{term: {name: 'Johny'}}, {range: {age: {lte: 42}}}]} }}}}
-
:must
Filter compiles into a boolmust
filter.Ex:
builder.filter{ name == 'Johny' }.filter{ age <= 42 }.filter_mode(:must) # => {body: {query: {filtered: { query: {...}, filter: {bool: {must: [{term: {name: 'Johny'}}, {range: {age: {lte: 42}}}]}} }}}}
-
:should
Filter compiles into a boolshould
filter.Ex:
builder.filter{ name == 'Johny' }.filter{ age <= 42 }.filter_mode(:should) # => {body: {query: {filtered: { query: {...}, filter: {bool: {should: [{term: {name: 'Johny'}}, {range: {age: {lte: 42}}}]}} }}}}
-
Any acceptable
minimum_should_match
value (1, '2', '75%') Filter compiles into boolshould
filter withminimum_should_match
set.Ex:
builder.filter{ name == 'Johny' }.filter{ age <= 42 }.filter_mode('50%') # => {body: {query: {filtered: { query: {...}, filter: {bool: { should: [{term: {name: 'Johny'}}, {range: {age: {lte: 42}}}], minimum_should_match: '50%' }} }}}}
Default value for :filter_mode
might be changed with ChewyQuery.filter_mode
config option.
ChewyQuery.filter_mode = :should ChewyQuery.filter_mode = '50%'
@see www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-and-filter.html @see www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-bool-filter.html @see www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-or-filter.html
# File lib/chewy_query/builder.rb, line 216 def filter_mode(value) chain{ criteria.update_options filter_mode: value } end
Elasticsearch highlight query option support
builder.query(...).highlight(fields: { ... })
@see www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-highlighting.html
# File lib/chewy_query/builder.rb, line 271 def highlight(value) chain{ criteria.update_request_options highlight: value } end
# File lib/chewy_query/builder.rb, line 840 def inspect "#<%s:%#016x @request=%s>" % [self.class, (object_id << 1), request] end
Sets elasticsearch size
search request param Default value is set in the elasticsearch and is 10.
builder.filter{ name == 'Johny' }.limit(100) # => {body: { query: {...}, size: 100 }}
@see www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-from-size.html
# File lib/chewy_query/builder.rb, line 247 def limit(value) chain{ criteria.update_request_options size: Integer(value) } end
Merges two queries. Merges all the values in criteria with the same rules as values added manually.
scope1 = builder.filter{ name == 'Johny' } scope2 = builder.filter{ age <= 42 } scope3 = builder.filter{ name == 'Johny' }.filter{ age <= 42 } scope1.merge(scope2) == scope3 # => true
# File lib/chewy_query/builder.rb, line 827 def merge(other) chain{ criteria.merge!(other.criteria) } end
Marks the criteria as having zero records. This scope always returns empty array without touching the elasticsearch server. All the chained calls of methods don't affect the result
UsersIndex.none.to_a # => [] UsersIndex.query(text: {name: 'Johny'}).none.to_a # => [] UsersIndex.none.query(text: {name: 'Johny'}).to_a # => []
# File lib/chewy_query/builder.rb, line 511 def none chain{ criteria.update_options(none: true) } end
Sets elasticsearch from
search request param
builder.filter{ name == 'Johny' }.offset(300) # => {body: { query: {...}, from: 300 }}
@see www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-from-size.html
# File lib/chewy_query/builder.rb, line 261 def offset(value) chain{ criteria.update_request_options from: Integer(value) } end
Sets search request field list
builder.only(:first_name, :last_name).only(:age) # => {body: { query: {...}, fields: ['first_name', 'last_name', 'age'] }}
@see www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-fields.html
# File lib/chewy_query/builder.rb, line 744 def only(*params) chain{ criteria.update_fields(params) } end
Cleans up previous search field list and sets the new one
builder.only(:first_name, :last_name).only!(:age) # => {body: { query: {...}, fields: ['age'] }}
@see www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-fields.html
# File lib/chewy_query/builder.rb, line 758 def only!(*params) chain{ criteria.update_fields(params, purge: true) } end
Sets search request sorting
builder.order(:first_name, :last_name).order(age: :desc).order(price: {order: :asc, mode: :avg}) # => {body: { query: {...}, sort: ['first_name', 'last_name', {age: 'desc'}, {price: {order: 'asc', mode: 'avg'}}] }}
@see www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-sort.html
# File lib/chewy_query/builder.rb, line 716 def order(*params) chain{ criteria.update_sort(params) } end
Adds one or more post_filter
to the search request Internally post_filters are stored as an array While the full query compilation this array compiles according to :post_filter_mode
option value
By default it joins inside and
filter See #post_filter_mode
chainable method for more info.
Also this method supports block DSL. See ChewyQuery::Builder::Filters
for more info.
builder.post_filter(term: {name: 'Johny'}).post_filter(range: {age: {lte: 42}}) builder.post_filter{ name == 'Johny' }.post_filter{ age <= 42 } # => {body: { post_filter: {and: [{term: {name: 'Johny'}}, {range: {age: {lte: 42}}}]} }}
If only one post_filter
was specified, it will become a result post_filter
as is, without joining.
builder.post_filter(term: {name: 'Johny'}) # => {body: { post_filter: {term: {name: 'Johny'}} }}
@see www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-post-filter.html
# File lib/chewy_query/builder.rb, line 619 def post_filter(params = nil, &block) params = Filters.new(&block).__render__ if block chain{ criteria.update_post_filters(params) } end
Acts the same way as `filter_mode`, but used for `post_filter`. Note that it fallbacks by default to `ChewyQuery.filter_mode` if `ChewyQuery.post_filter_mode` is nil.
builder.post_filter{ name == 'Johny' }.post_filter{ age <= 42 }.post_filter_mode(:and) builder.post_filter{ name == 'Johny' }.post_filter{ age <= 42 }.post_filter_mode(:should) builder.post_filter{ name == 'Johny' }.post_filter{ age <= 42 }.post_filter_mode('50%')
@see www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-and-filter.html @see www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-bool-filter.html @see www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-or-filter.html
# File lib/chewy_query/builder.rb, line 232 def post_filter_mode(value) chain{ criteria.update_options post_filter_mode: value } end
Adds one or more query to the search request Internally queries are stored as an array While the full query compilation this array compiles according to :query_mode
option value
By default it joines inside must
query See #query_mode
chainable method for more info.
builder.query(match: {name: 'Johny'}).query(range: {age: {lte: 42}}) # => {body: { query: {bool: {must: [{match: {name: 'Johny'}}, {range: {age: {lte: 42}}}]}} }}
If only one query was specified, it will become a result query as is, without joining.
builder.query(match: {name: 'Johny'}) # => {body: { query: {match: {name: 'Johny'}} }}
@see www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-queries.html
# File lib/chewy_query/builder.rb, line 554 def query(params) chain{ criteria.update_queries(params) } end
Sets query compilation mode for search request. Not used if only one filter for search is specified. Possible values:
-
:must
Default value. Query compiles into a boolmust
query.Ex:
builder.query(text: {name: 'Johny'}).query(range: {age: {lte: 42}}) # => {body: { query: {bool: {must: [{text: {name: 'Johny'}}, {range: {age: {lte: 42}}}]}} }}
-
:should
Query compiles into a boolshould
query.Ex:
builder.query(text: {name: 'Johny'}).query(range: {age: {lte: 42}}).query_mode(:should) # => {body: { query: {bool: {should: [{text: {name: 'Johny'}}, {range: {age: {lte: 42}}}]}} }}
-
Any acceptable
minimum_should_match
value (1, '2', '75%') Query compiles into a boolshould
query withminimum_should_match
set.Ex:
builder.query(text: {name: 'Johny'}).query(range: {age: {lte: 42}}).query_mode('50%') # => {body: { query: {bool: { should: [{text: {name: 'Johny'}}, {range: {age: {lte: 42}}}], minimum_should_match: '50%' }} }}
-
:dis_max
Query compiles into adis_max
query.Ex:
builder.query(text: {name: 'Johny'}).query(range: {age: {lte: 42}}).query_mode(:dis_max) # => {body: { query: {dis_max: {queries: [{text: {name: 'Johny'}}, {range: {age: {lte: 42}}}]}} }}
-
Any Float value (0.0, 0.7, 1.0) Query compiles into a
dis_max
query withtie_breaker
option set.Ex:
builder.query(text: {name: 'Johny'}).query(range: {age: {lte: 42}}).query_mode(0.7) # => {body: { query: {dis_max: { queries: [{text: {name: 'Johny'}}, {range: {age: {lte: 42}}}], tie_breaker: 0.7 }} }}
Default value for :query_mode
might be changed with ChewyQuery.query_mode
config option.
ChewyQuery.query_mode = :dis_max ChewyQuery.query_mode = '50%'
@see www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-dis-max-query.html @see www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html
# File lib/chewy_query/builder.rb, line 140 def query_mode(value) chain{ criteria.update_options query_mode: value } end
Adds a random score to the search request. All scores are added to the search request and combinded according to boost_mode
and score_mode
This probably only makes sense if you specifiy a filter for the random score as well.
If you do not pass in a seed value, Time.now will be used
builder.random_score(23, filter: { foo: :bar}) # => {body: query: { function_score: { query: { ...}, functions: [{ random_score: { seed: 23 }, filter: { foo: :bar } }] } } }
# File lib/chewy_query/builder.rb, line 377 def random_score(seed = Time.now, options = {}) scoring = options.merge(random_score: { seed: seed.to_i }) chain{ criteria.update_scores(scoring) } end
Cleans up previous search sorting and sets the new one
builder.order(:first_name, :last_name).order(age: :desc).reorder(price: {order: :asc, mode: :avg}) # => {body: { query: {...}, sort: [{price: {order: 'asc', mode: 'avg'}}] }}
@see www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-sort.html
# File lib/chewy_query/builder.rb, line 730 def reorder(*params) chain{ criteria.update_sort(params, purge: true) } end
# File lib/chewy_query/builder.rb, line 836 def request @request ||= criteria.request_body.merge(index: index_name, type: types) end
Elasticsearch rescore query option support
builder.query(...).rescore(query: { ... })
@see www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-rescore.html
# File lib/chewy_query/builder.rb, line 281 def rescore(value) chain{ criteria.update_request_options(rescore: value) } end
Sets the scoring mode for combining function scores/boosts Not used if no score functions are specified. Possible values:
-
:multiply
Default value. Scores are multiplied.Ex:
builder.score_mode('multiply').script_score('doc['boost'].value') # => {body: {query: function_score: { query: {...}, score_mode: 'multiply', functions: [ ... ] }}}
-
:sum
Scores are summed. -
:avg
Scores are averaged. -
:first
The first function that has a matching filter is applied. -
:max
Maximum score is used. -
:min
Minimum score is used
Default value for :score_mode
might be changed with ChewyQuery.score_mode
config option.
ChewyQuery.score_mode = :first
@see www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html
# File lib/chewy_query/builder.rb, line 702 def score_mode(value) chain{ criteria.update_options(score_mode: value) } end
Adds a script function to score the search request. All scores are added to the search request and combinded according to boost_mode
and score_mode
builder.script_score("doc['boost'].value", filter: { term: {foo: :bar} }) # => {body: query: { function_score: { query: { ...}, functions: [{ script_score: { script: "doc['boost'].value" }, filter: { term: { foo: :bar } } } }] } } }
# File lib/chewy_query/builder.rb, line 324 def script_score(script, options = {}) scoring = options.merge(script_score: { script: script }) chain{ criteria.update_scores(scoring) } end
Setups strategy for top-level filtered query
builder.filter { name == 'Johny'}.strategy(:leap_frog) # => {body: { query: { filtered: { filter: { term: { name: 'Johny' } }, strategy: 'leap_frog' } } }}
# File lib/chewy_query/builder.rb, line 527 def strategy(value = nil) chain{ criteria.update_options(strategy: value) } end
Sets elasticsearch suggest
search request param
builder.suggest(name: {text: 'Joh', term: {field: 'name'}}) # => {body: { query: {...}, suggest: { text: 'Joh', term: { field: 'name' } } }}
@see www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-suggesters.html
# File lib/chewy_query/builder.rb, line 497 def suggest(params = nil) chain{ criteria.update_suggest params } end
Specify types participating in the search result Works via types
filter. Always merged with another filters with the and
filter.
builder.types(:admin, :manager).filters{ name == 'Johny' }.filters{ age <= 42 } # => {body: {query: {filtered: { query: {...}, filter: {and: [ {or: [ {type: {value: 'admin'}}, {type: {value: 'manager'}} ]}, {term: {name: 'Johny'}}, {range: {age: {lte: 42}}} ]} }}}} builder.types(:admin, :manager).filters{ name == 'Johny' }.filters{ age <= 42 }.filter_mode(:or) # => {body: {query: {filtered: { query: {...}, filter: {and: [ {or: [ {type: {value: 'admin'}}, {type: {value: 'manager'}} ]}, {or: [ {term: {name: 'Johny'}}, {range: {age: {lte: 42}}} ]} ]} }}}}
@see www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-type-filter.html
# File lib/chewy_query/builder.rb, line 796 def types(*params) if params.any? chain{ criteria.update_types(params) } else @types end end
Acts the same way as types
, but cleans up previously set types
builder.types(:admin).types!(:manager) # => {body: {query: {filtered: { query: {...}, filter: {type: {value: 'manager'}} }}}}
@see www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-type-filter.html
# File lib/chewy_query/builder.rb, line 814 def types!(*params) chain{ criteria.update_types(params, purge: true) } end
Adds version
parameter to search request.
builder.filter(term: {name: 'Johny'}).version builder.filter(term: {name: 'Johny'}).version(true) builder.filter(term: {name: 'Johny'}).version(false)
Calling version without any arguments sets version flag to true.
builder.filter(term: {name: 'Johny'}).version
@see www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-version.html
# File lib/chewy_query/builder.rb, line 67 def version(value = nil) chain{ criteria.update_request_options version: (value.nil? ? true : value) } end
Protected Instance Methods
# File lib/chewy_query/builder.rb, line 850 def initialize_clone(other) @criteria = other.criteria.clone reset end
# File lib/chewy_query/builder.rb, line 846 def reset @request, @delete_all_request = nil end
Private Instance Methods
# File lib/chewy_query/builder.rb, line 861 def chain(&block) clone.tap{|q| q.instance_eval(&block) } end
# File lib/chewy_query/builder.rb, line 857 def index_name index.respond_to?(:index_name) ? index.index_name : index end