Module: ElasticsearchRecord::Relation::QueryMethods

Defined in:
lib/elasticsearch_record/relation/query_methods.rb

Instance Method Summary collapse

Instance Method Details

#aggregate(*args) ⇒ Object Also known as: aggs

create or add an aggregation to the query.

Examples:

aggregate(:total, { sum: {field: :amount})


73
74
75
76
# File 'lib/elasticsearch_record/relation/query_methods.rb', line 73

def aggregate(*args)
  check_if_method_has_arguments!(__callee__, args)
  spawn.aggregate!(*args)
end

#aggregate!(opts, *rest) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/elasticsearch_record/relation/query_methods.rb', line 80

def aggregate!(opts, *rest)
  # :nodoc:
  case opts
  when Symbol, String
    self.aggs_clause += build_query_clause(opts, rest)
  when Hash
    opts.each do |key, value|
      self.aggs_clause += build_query_clause(key, value)
    end
  else
    raise ArgumentError, "Unsupported argument type for aggregate: #{opts}"
  end

  self
end

#configure(*args) ⇒ Object

sets or overwrites additional arguments for the whole query (not the current 'query-node' - the whole query). Previously defined arguments (like size or from) can also be overwritten. Providing a nil value will remove the key - this is useful to force remove of keys.

Providing the special key :__query__ will directly access the query object, to alter query-related values (like 'refresh, arguments, columns, ...' - see @ Arel::Collectors::ElasticsearchQuery

Examples:

# adds {refresh true} to the query
configure(:refresh, true)

# overwrites or sets {from: 50} but removes the :sort key
configure({from: 50, sort: nil})

# sets the query's 'refresh' to true
configure(:__query__, refresh: true)

Parameters:

  • args (Array)


48
49
50
# File 'lib/elasticsearch_record/relation/query_methods.rb', line 48

def configure(*args)
  spawn.configure!(*args)
end

#configure!(*args) ⇒ self

same like #configure!, but on the same relation (no spawn)

Returns:

  • (self)


54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/elasticsearch_record/relation/query_methods.rb', line 54

def configure!(*args)
  check_if_method_has_arguments!(__callee__, args)

  if args.length == 1 && args.first.is_a?(Hash)
    self.configure_value = self.configure_value.merge(args[0])
  elsif args.length == 2 && args[0] == :__query__
    tmp = self.configure_value[:__query__] || []
    tmp << args[1]
    self.configure_value = self.configure_value.merge(:__query__ => tmp)
  elsif args.length == 2
    self.configure_value = self.configure_value.merge(args[0] => args[1])
  end

  self
end

#filter(*args) ⇒ Object

adds a filter clause.

Examples:

filter({terms: ...})


134
135
136
137
# File 'lib/elasticsearch_record/relation/query_methods.rb', line 134

def filter(*args)
  check_if_method_has_arguments!(__callee__, args)
  spawn.filter!(*args)
end

#filter!(opts, *rest) ⇒ Object



139
140
141
142
143
144
# File 'lib/elasticsearch_record/relation/query_methods.rb', line 139

def filter!(opts, *rest)
  # :nodoc:
  set_default_kind!
  self.query_clause += build_query_clause(:filter, opts, rest)
  self
end

#joinsObject

unsupported method

Raises:

  • (ActiveRecord::StatementInvalid)


6
7
8
# File 'lib/elasticsearch_record/relation/query_methods.rb', line 6

def joins(*)
  raise ActiveRecord::StatementInvalid, 'Unsupported method "joins"'
end

#kind(value) ⇒ Object

sets or overwrites the query kind (e.g. compound queries -> :bool, :boosting, :constant_score, ...). Also other query kinds like :intervals, :match, ... are allowed. Alternatively the +#query+-method can also be used to provide a kind with arguments.

Parameters:

  • value (String, Symbol)
    • the kind


19
20
21
# File 'lib/elasticsearch_record/relation/query_methods.rb', line 19

def kind(value)
  spawn.kind!(value)
end

#kind!(value) ⇒ Object

same like #kind, but on the same relation (no spawn)



24
25
26
27
28
# File 'lib/elasticsearch_record/relation/query_methods.rb', line 24

def kind!(value)
  # :nodoc:
  self.kind_value = value
  self
end

#must(*args) ⇒ Object

adds a must clause.

Examples:

must({terms: ...})


164
165
166
167
# File 'lib/elasticsearch_record/relation/query_methods.rb', line 164

def must(*args)
  check_if_method_has_arguments!(__callee__, args)
  spawn.must!(*args)
end

#must!(opts, *rest) ⇒ Object



169
170
171
172
173
174
# File 'lib/elasticsearch_record/relation/query_methods.rb', line 169

def must!(opts, *rest)
  # :nodoc:
  set_default_kind!
  self.query_clause += build_query_clause(:must, opts, rest)
  self
end

#must_not(*args) ⇒ Object

adds a must_not clause.

Examples:

filter({terms: ...})


149
150
151
152
# File 'lib/elasticsearch_record/relation/query_methods.rb', line 149

def must_not(*args)
  check_if_method_has_arguments!(__callee__, args)
  spawn.must_not!(*args)
end

#must_not!(opts, *rest) ⇒ Object



154
155
156
157
158
159
# File 'lib/elasticsearch_record/relation/query_methods.rb', line 154

def must_not!(opts, *rest)
  # :nodoc:
  set_default_kind!
  self.query_clause += build_query_clause(:must_not, opts, rest)
  self
end

#none!Object

:nodoc:



191
192
193
194
195
# File 'lib/elasticsearch_record/relation/query_methods.rb', line 191

def none! # :nodoc:
  @none = true
  # tell the query it 'failed'
  configure!(:__query__, status: :failed)
end

#or!(other) ⇒ Object



247
248
249
250
251
# File 'lib/elasticsearch_record/relation/query_methods.rb', line 247

def or!(other)
  self.query_clause = self.query_clause.or(other.query_clause)

  super(other)
end

#query(*args) ⇒ Object

add a whole query 'node' to the query.

Examples:

query(:bool, {filter: ...})


119
120
121
122
# File 'lib/elasticsearch_record/relation/query_methods.rb', line 119

def query(*args)
  check_if_method_has_arguments!(__callee__, args)
  spawn.query!(*args)
end

#query!(kind, opts, *rest) ⇒ Object



124
125
126
127
128
129
# File 'lib/elasticsearch_record/relation/query_methods.rb', line 124

def query!(kind, opts, *rest)
  # :nodoc:
  kind!(kind)
  self.query_clause += build_query_clause(opts.keys[0], opts.values[0], rest)
  self
end

#refresh(value = true) ⇒ Object

sets the query's refresh value.

Parameters:

  • value (Boolean) (defaults to: true)

    (default: true)



98
99
100
# File 'lib/elasticsearch_record/relation/query_methods.rb', line 98

def refresh(value = true)
  spawn.refresh!(value)
end

#refresh!(value = true) ⇒ Object



102
103
104
# File 'lib/elasticsearch_record/relation/query_methods.rb', line 102

def refresh!(value = true)
  configure!(:__query__, refresh: value)
end

#select(*fields) ⇒ Object

overwrite to prevent metadata fields within the projection. Metadata fields (like '_id' or '_score') are NOT part of the _source node, so they cannot be resolved through the +_source+-filter this method builds - providing them would silently create a filter that never matches. HINT: This is different to the +pluck+-method which allows to resolve meta keys directly. see @ Arel::Visitors::ElasticsearchQuery#visit_Selects

Parameters:

  • fields (Array)


285
286
287
288
289
290
291
292
293
294
295
296
297
# File 'lib/elasticsearch_record/relation/query_methods.rb', line 285

def select(*fields)
  # IMPORTANT: +select+ can also be called with a block (and without any fields) - in this case
  # ActiveRecord directly forwards to +super()+, so we must not interfere here.
  if fields.any? && (invalid = _invalid_projection_fields(fields)).present?
    raise(ActiveRecord::UnknownAttributeReference,
          "Unable to select metadata attributes: #{invalid.map(&:inspect).join(", ")}. " \
          "Metadata fields are not part of the '_source' node but are always returned and accessible within the record. " \
          "(e.g. #{klass.name}.first.#{invalid.first})."
    )
  end

  super
end

#should(*args) ⇒ Object

adds a should clause.

Examples:

should({terms: ...})


179
180
181
182
# File 'lib/elasticsearch_record/relation/query_methods.rb', line 179

def should(*args)
  check_if_method_has_arguments!(__callee__, args)
  spawn.should!(*args)
end

#should!(opts, *rest) ⇒ Object



184
185
186
187
188
189
# File 'lib/elasticsearch_record/relation/query_methods.rb', line 184

def should!(opts, *rest)
  # :nodoc:
  set_default_kind!
  self.query_clause += build_query_clause(:should, opts, rest)
  self
end

#timeout(value = true) ⇒ Object

sets the query's timeout value.

Parameters:

  • value (Boolean) (defaults to: true)

    (default: true)



108
109
110
# File 'lib/elasticsearch_record/relation/query_methods.rb', line 108

def timeout(value = true)
  spawn.timeout!(value)
end

#timeout!(value = true) ⇒ Object



112
113
114
# File 'lib/elasticsearch_record/relation/query_methods.rb', line 112

def timeout!(value = true)
  configure!(:__query__, timeout: value)
end

#unscope!(*args) ⇒ Object



253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
# File 'lib/elasticsearch_record/relation/query_methods.rb', line 253

def unscope!(*args)
  # :nodoc:
  self.unscope_values += args

  args.each do |scope|
    case scope
    when Symbol
      unless _valid_unscoping_values.include?(scope)
        raise ArgumentError, "Called unscope() with invalid unscoping argument ':#{scope}'. Valid arguments are :#{_valid_unscoping_values.to_a.join(", :")}."
      end
      assert_mutability!
      @values.delete(scope)
    when Hash
      scope.each do |key, target_value|
        target_query_clause = build_query_clause(key, target_value)
        self.query_clause   -= target_query_clause
      end
    else
      raise ArgumentError, "Unrecognized scoping: #{args.inspect}. Use .unscope(where: :attribute_name) or .unscope(:order), for example."
    end
  end

  self
end

#where!(opts, *rest) ⇒ Object

creates a condition on the relation. There are several possibilities to call this method.

Examples:

# create a simple 'term' condition on the query[:filter] param
where({name: 'hans'})
#> query[:filter] << { term: { name: 'hans' } }

# create a simple 'terms' condition on the query[:filter] param
where({name: ['hans','peter']})
#> query[:filter] << { terms: { name: ['hans','peter'] } }

where(:must_not, term: {name: 'horst'})
where(:query_string, "(new york OR dublin)", fields: ['name','description'])

# nested array
where([ [:filter, {...}], [:must_not, {...}]])

# invalidate query
where(:none)


218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/elasticsearch_record/relation/query_methods.rb', line 218

def where!(opts, *rest)
  # :nodoc:
  case opts
  when Symbol
    case opts
    when :none
      none!
    when :filter, :must, :must_not, :should
      # check the first provided parameter +opts+ and validate, if this is an alias for "must, must_not, should or filter".
      # if true, we expect the rest[0] to be a hash.
      # For this correlation we forward this as RAW-data without check & manipulation
      send("#{opts}!", *rest)
    else
      raise ArgumentError, "Unsupported prefix type '#{opts}'. Allowed types are: :filter, :must, :must_not, :should"
    end
  when Array
    # check if this is a nested array of multiple [<kind>,<data>]
    if opts[0].is_a?(Array)
      opts.each { |item| where!(*item) }
    else
      where!(*opts, *rest)
    end
  else
    self.where_clause += build_where_clause(opts, rest)
  end

  self
end