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

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

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

Constructor Details

#initialize(base = nil, options = {}) ⇒ WhereClause

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]
)

Options Hash (options):

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

    Whether the new state is inverted

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

    Whether the new state is should

See Also:



65
66
67
68
# File 'lib/stretchy/clauses/where_clause.rb', line 65

def initialize(base = nil, options = {})
  super(base)
  add_params(options)
end

Class Method Details

.tmp(options = {}) ⇒ WhereClause

Creates a temporary context by initializing a new Base object. Used primarily in BoostWhereClause



33
34
35
36
37
38
39
# File 'lib/stretchy/clauses/where_clause.rb', line 33

def self.tmp(options = {})
  if options.delete(:inverse)
    self.new(Builders::ShellBuilder.new).not(options)
  else
    self.new(Builders::ShellBuilder.new, options)
  end
end

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
)

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



128
129
130
131
132
133
134
# File 'lib/stretchy/clauses/where_clause.rb', line 128

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(options = {}) ⇒ WhereClause

Switches current state to inverted. Options passed here are equivalent to those passed to #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, "options"]
)


204
205
206
207
208
# File 'lib/stretchy/clauses/where_clause.rb', line 204

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

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

Add a range filter to the current context. While you can pass a Range object to Base#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
)

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



100
101
102
103
104
105
# File 'lib/stretchy/clauses/where_clause.rb', line 100

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

#should(options = {}) ⇒ WhereClause

Switches the current state to should. Options passed here are equivalent to those passed to #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 options

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

Inverted should options

query.should.not(
  exists_field: nil
) 

See Also:



236
237
238
239
240
241
# File 'lib/stretchy/clauses/where_clause.rb', line 236

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

#should?true, false

Accessor for @should



74
75
76
# File 'lib/stretchy/clauses/where_clause.rb', line 74

def should?
  !!@should
end

#terms(params = {}) ⇒ 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~~!'
)

See Also:



175
176
177
178
# File 'lib/stretchy/clauses/where_clause.rb', line 175

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

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

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



250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
# File 'lib/stretchy/clauses/where_clause.rb', line 250

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