Class: Stretchy::Clauses::WhereClause

Inherits:
Base
  • Object
show all
Defined in:
lib/stretchy/clauses/where_clause.rb

Overview

A Where clause inherits the same state as any clause, but has a few possible states to transition to. You can call #range and #geo to add their respective filters, or you can transition to the inverted state via #not, or the should state via #should

STATES:

  • inverted: any filters added in this state will be inverted, ie the document must NOT match said filters.
  • should: any filters added in this state will be applied to a should block. Documents which do not match these filters will be returned, but documents which do match will have a higher relevance score.

Author:

  • [atevans]

Instance Attribute Summary

Attributes inherited from Base

#base

Instance Method Summary collapse

Methods inherited from Base

#aggregations, #boost, #explain, #fields, #get_aggregations, #get_explain, #get_fields, #get_limit, #get_offset, #get_page, #initialize, #inverse?, #limit, #offset, #page, #query_results, #root

Constructor Details

This class inherits a constructor from Stretchy::Clauses::Base

Instance Method Details

#geo(field, options = {}) ⇒ self

Adds a geo distance filter to the current context. Documents must have a geo_point field that is within the specified distance of the passed parameters.

Examples:

Searching by distance from a point

query.where.geo(:coords,
  distance: '27km',
  lat: 33.3,
  lng: 29.2
)

Parameters:

  • field (String, Symbol)

    The field this filter will be applied to.

  • options (defaults to: {})

    = {} [Hash] Options for the geo distance filter

Options Hash (options):

  • :distance (String) — default: nil

    The maximum distance from the specified origin. Use an Elastic distance format such as '21mi' or '37km'

  • :lat (Float) — default: nil

    The latitude of the origin point. Can also be specified as :latitude

  • :lng (Float) — default: nil

    The longitude of the origin point. Can also be specified as :lon or :longitude

Returns:

  • (self)

    query state with geo distance filter applied



115
116
117
118
119
120
121
# File 'lib/stretchy/clauses/where_clause.rb', line 115

def geo(field, options = {})
  distance = options[:distance]
  options[:inverse] = true if inverse?
  options[:should]  = true if should?
  base.where_builder.add_geo(field, distance, options)
  self
end

#not(params = {}, options = {}) ⇒ WhereClause

Switches current state to inverted. Options passed here are equivalent to those passed to Base#initialize, except documents must not match these filters.

Can be chained with #should to produce inverted should queries

Examples:

Inverting filters

query.where.not(
  must_exist: nil,
  not_matching: "this string",
  not_in: [45, 67, 99],
  not_in_range: 89..23
)

Inverted should filters

query.should.not(
  match_field: [:these, "params"]
)

Parameters:

  • params (defaults to: {})

    = {} [Hash] params to filter on

Returns:

  • (WhereClause)

    inverted query state with not filters applied.



192
193
194
195
196
# File 'lib/stretchy/clauses/where_clause.rb', line 192

def not(params = {}, options = {})
  @inverse = true
  add_params(params, options)
  self
end

#range(field, options = {}) ⇒ self

Add a range filter to the current context. While you can pass a Range object to #where, this allows you to specify an open-ended range, such as only specifying the minimum or maximum value.

Examples:

Adding a range filter

query.where.range(:my_range_field,
  min: 33,
  exclusive: true
)

Parameters:

  • field (String, Symbol)

    The field to filter with this range

  • options (defaults to: {})

    = {} [Hash] Options for the range

Options Hash (options):

  • :min (Numeric) — default: nil

    Minimum. Ranges are inclusive by default

  • :max (Numeric) — default: nil

    Maximum. Ranges are inclusive by default

  • :exclusive (true, false) — default: nil

    Overrides default and makes the range exclusive - equivalent to passing both :exclusive_min and :exclusive_max

  • :exclusive_min (true, false) — default: nil

    Overrides default and makes the minimum exclusive

  • :exclusive_max (true, false) — default: nil

    Overrides default and makes the maximum exclusive

Returns:

  • (self)

    query state with range filter applied



87
88
89
90
91
92
# File 'lib/stretchy/clauses/where_clause.rb', line 87

def range(field, options = {})
  options[:inverse] = true if inverse?
  options[:should]  = true if should?
  base.where_builder.add_range(field, options)
  self
end

#should(params = {}, options = {}) ⇒ WhereClause

Switches the current state to should. Options passed here are equivalent to those passed to Base#initialize, except documents which do not match are still returned with a lower score than documents which do match.

Can be chained with #not to produce inverted should queries

CAUTION: Documents that don't match at least one should clause will not be returned.

Examples:

Specifying should params

query.should(
  field: [99, 27]
)

Inverted should params

query.should.not(
  exists_field: nil
) 

Parameters:

  • params (defaults to: {})

    = {} [Hash] params to filter on

Returns:

  • (WhereClause)

    should query state with should filters applied

See Also:



224
225
226
227
228
229
# File 'lib/stretchy/clauses/where_clause.rb', line 224

def should(params = {}, options = {})
  @inverse = false
  @should  = true
  add_params(params, options)
  self
end

#should?true, false

Accessor for @should

Returns:

  • (true, false)

    @should



61
62
63
# File 'lib/stretchy/clauses/where_clause.rb', line 61

def should?
  !!@should
end

#terms(params = {}, options = {}) ⇒ WhereClause Also known as: exact

Used for passing strings or symbols in a .where method, and using the un-analyzed Terms filter instead of an analyzed and parsed Match Query.

This would be useful if you have a set of specific strings a field could be in, such as: role: ['admin_user', 'company_manager'] and you want to query for those exact strings without the usual downcase / punctuation removal analysis.

CAUTION: The keys indexed by elastic may be analyzed - downcased, punctuation removed, etc. Using a terms filter in this case will not work . Hence the default of using a match query for strings and symbols instead.

Examples:

Querying for exact terms

query.where.terms(
  status_field: 'working_fine_today',
  number: 27,
  date: Date.today
)

Not matching exact terms

query.where.not.terms(
  email: '[email protected]'
)

Should match exact terms

query.should.terms(
  hacker_alias: '!!ic3y.h0t~~!'
)

Parameters:

Returns:

See Also:



162
163
164
165
166
# File 'lib/stretchy/clauses/where_clause.rb', line 162

def terms(params = {}, options = {})
  options[:exact] = true
  add_params(params, options)
  self
end

#to_boost(weight = nil) ⇒ Boosts::FilterBoost

Converts the current context into a boost to be passed into a FunctionScoreQuery.

Parameters:

  • weight (defaults to: nil)

    = nil [Numeric] A weight for the FunctionScoreQuery

Returns:



238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# File 'lib/stretchy/clauses/where_clause.rb', line 238

def to_boost(weight = nil)
  weight ||= Stretchy::Boosts::FilterBoost::DEFAULT_WEIGHT

  if base.match_builder.any? && base.where_builder.any?
    Stretchy::Boosts::FilterBoost.new(
      filter: Stretchy::Filters::QueryFilter.new(
        Stretchy::Queries::FilteredQuery.new(
          query:  base.match_builder.to_query,
          filter: base.where_builder.to_filter
        )
      ),
      weight: weight
    )
  
  elsif base.match_builder.any?
    Stretchy::Boosts::FilterBoost.new(
      filter: Stretchy::Filters::QueryFilter.new(
        base.match_builder.to_query
      ),
      weight: weight
    )

  elsif base.where_builder.any?
    Stretchy::Boosts::FilterBoost.new(
      filter: base.where_builder.to_filter,
      weight: weight
    )
  end
end

#where(params = {}, options = {}) ⇒ Object

Options passed to the initializer will be interpreted as filters to be added to the query. This is similar to ActiveRecord's where method.

Examples:

Apply ActiveRecord-like filters

query.where(
  string_field: "string",
  must_not_exist: nil,
  in_range: 27..33,
  included_in: [47, 23, 86]
)

Parameters:

  • base (Base)

    Used to intialize the new state from the previous clause

  • params (defaults to: {})

    = {} [Hash] filters to be applied to the new state

Options Hash (params):

  • :inverted (true, false) — default: nil

    Whether the new state is inverted

  • :should (true, false) — default: nil

    Whether the new state is should

See Also:



50
51
52
53
54
55
# File 'lib/stretchy/clauses/where_clause.rb', line 50

def where(params = {}, options = {})
  @inverse = false
  @should  = false
  add_params(params, options)
  self
end