Class: ElasticSearchQuery

Inherits:
Object
  • Object
show all
Defined in:
lib/elastic_search_query.rb

Class Method Summary collapse

Class Method Details

.append_query_filter(query, filter) ⇒ Object

this appends bools structure containing must, should and must_not in an existing query under the filter context if filter is not present in the existing query, the entire bool structure is assigned, if filter is present, then the bool structure is merged with the existing structure under the filter context finally the filter priovided in the method params is appended in the must clause

Parameters:

  • query (Hash)

    main query

  • filter (Hash)

    assigned in the must clause of the main query



428
429
430
431
432
433
434
435
436
437
438
439
# File 'lib/elastic_search_query.rb', line 428

def self.append_query_filter(query, filter)
  bool_query = get_bool_filter_structure
  if query[:query][:bool][:filter].nil?
    query[:query][:bool][:filter] = bool_query
  else
    bool_query[:bool].each { |key, val|
      query[:query][:bool][:filter][:bool][key] = [] unless query[:query][:bool][:filter][:bool].key? (key)
    }
  end
  query[:query][:bool][:filter][:bool][:must].push(filter)
  query
end

.append_size_filter(query, size) ⇒ Object

sets the max number of results to be returned by the query



442
443
444
445
# File 'lib/elastic_search_query.rb', line 442

def self.append_size_filter(query, size)
  query[:size] = size
  query
end

.dis_max_query(queries = []) ⇒ Object

returns a structure of dis_max query.

Parameters:

  • queries (Array) (defaults to: [])

    , array of queries used for union

Raises:

  • (ArgumentError)


374
375
376
377
378
379
380
381
# File 'lib/elastic_search_query.rb', line 374

def self.dis_max_query queries=[]
  raise ArgumentError.new("queries is not an Array") unless queries.instance_of? Array
  return {
    dis_max: {
      queries: queries
    }
  }
end

.filtered_aggregation(name, aggregation, filter) ⇒ Object

constructs a structure that defines a single bucket which matches a specified filter

Parameters:

  • name (String)

    name of the aggregation

  • aggregation (Hash)

    specifying the aggregations (eg. Average)



301
302
303
304
305
306
307
308
309
310
# File 'lib/elastic_search_query.rb', line 301

def self.filtered_aggregation name, aggregation, filter
  {
    :aggs => {
      name.intern => {
        filter: filter,
        aggs: aggregation
      }
    }
  }
end

.function_score(query, seed) ⇒ Object



357
358
359
360
361
362
363
364
365
366
367
368
369
370
# File 'lib/elastic_search_query.rb', line 357

def self.function_score query, seed
  {
    function_score: {
      query: query,
      functions: [
        {
          random_score: {
            seed: seed
          }
        }
        ]
    }
  }
end

.get_bool_filter_structureObject

returns basic bool structure with should, must and mus_not clause



165
166
167
168
169
170
171
172
173
# File 'lib/elastic_search_query.rb', line 165

def self.get_bool_filter_structure
  {
    bool: {
      must: [],
      should: [],
      must_not: []
    }
  }
end

.get_constant_score_filter_structure(filter = {}, boost = 1) ⇒ Object

returns constant score filter structure



16
17
18
19
20
21
22
23
# File 'lib/elastic_search_query.rb', line 16

def self.get_constant_score_filter_structure filter = {}, boost = 1
  {
    :constant_score => {
      :filter => filter,
      :boost => boost
    }
  }
end

.get_constant_score_query_structure(query = {}, boost = 1) ⇒ Object

returns constant score query structure



26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/elastic_search_query.rb', line 26

def self.get_constant_score_query_structure query = {}, boost = 1
 {
   constant_score: {
     filter: {
         bool: {
             must: query
         }
     },
     boost: boost
   }
 }
end

.get_exists_filter(field) ⇒ Object

returns exists filter



40
41
42
43
44
45
46
47
48
49
50
# File 'lib/elastic_search_query.rb', line 40

def self.get_exists_filter field
  {
    constant_score: {
      filter: {
        exists: {
          field: field
        }
      }
    }
  }
end

.get_filtered_structureObject

returns filtered_structure



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/elastic_search_query.rb', line 120

def self.get_filtered_structure
  {
    bool: {
        must: [],
        should: [],
        must_not: [],
        filter: {
            bool: {
                must: [],
                should: [],
                must_not: []
            }
        }
    }
  }
end

.get_ids_filter_query(ids) ⇒ Object

builds ids query with provided values



290
291
292
293
294
# File 'lib/elastic_search_query.rb', line 290

def self.get_ids_filter_query ids
  ids_query_structure = get_ids_query_structure
  ids_query_structure[:ids][:values] = ids
  ids_query_structure
end

.get_ids_query_structureObject

returns the structure for ids matching



7
8
9
10
11
12
13
# File 'lib/elastic_search_query.rb', line 7

def self.get_ids_query_structure
  {
    :ids => {
      :values => []
    }
  }
end

.get_match_phrase_prefix_query(field, prefix) ⇒ Object

returns structure for match_phrase_prefix

Raises:

  • (ArgumentError)


79
80
81
82
83
84
85
86
# File 'lib/elastic_search_query.rb', line 79

def self.get_match_phrase_prefix_query field, prefix
    raise ArgumentError.new("field and prefix should be strings") unless (field.is_a? String) && (prefix.is_a? String)
    return {
      :match_phrase_prefix => {
        field => prefix
      }
    }
end

.get_metrics_aggregations_query(name, comparator, field_name) ⇒ Object

returns a generic metrics aggregation by providing the comparator

Parameters:

  • name (String)

    name of the aggregation

  • comparator (String)

    the metric to be used (eg. cardinality, avg)

  • field_name (String)

    field on which aggregation is used



263
264
265
266
267
268
269
270
271
# File 'lib/elastic_search_query.rb', line 263

def self.get_metrics_aggregations_query name, comparator, field_name
  query = {
    name => {
      comparator => {
        field: field_name
      }
    }
  }
end

.get_nested_aggregation_query(name, path, aggregation) ⇒ Object

this helps to contruct a structure where we can use aggregations on the nested objects also.

Parameters:

  • name (String)

    name of the aggregation

  • path (String)

    path to the nested object

  • field_name (String)

    field on which aggregation is used

  • aggregation (Hash)

    specifying the aggregations (eg. Average)



278
279
280
281
282
283
284
285
286
287
# File 'lib/elastic_search_query.rb', line 278

def self.get_nested_aggregation_query name, path, aggregation
  query = {
    name => {
      nested: {
        path: path
      },
      aggregations: aggregation
    }
  }
end

.get_nested_exists_query(field_name) ⇒ Object

get nested query to search on nested objects



411
412
413
414
415
416
417
418
419
420
# File 'lib/elastic_search_query.rb', line 411

def self.get_nested_exists_query field_name
  {
    nested: {
      path: field_name,
      query: {
        match_all: {}
      }
    }
  }
end

.get_nested_filter_structure(path, query = {}) ⇒ Object

With Elasticsearch 6.1 nested filter has been replaced with nested query nested filter structure



54
55
56
57
58
59
60
61
# File 'lib/elastic_search_query.rb', line 54

def self.get_nested_filter_structure path, query = {}
  {
    :nested => {
      :path => path,
      :query => query
    }
  }
end

.get_nested_query_structure(path, query = {}, score_mode = nil) ⇒ Object

returns nested query structure

Raises:

  • (ArgumentError)


64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/elastic_search_query.rb', line 64

def self.get_nested_query_structure path, query = {}, score_mode=nil
  raise ArgumentError.new("path has to be a string") unless (path.is_a? String)
  subquery = {
    :nested => {
      :path => path,
      :query => query
    }
  }
  if Constants::FUNCTION_SCORE_METHODS.include? score_mode
    subquery[:nested][:score_mode] = score_mode
  end
  return subquery
end

.get_nested_terms_query(path, field, value) ⇒ Object

returns nested terms query



150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/elastic_search_query.rb', line 150

def self.get_nested_terms_query(path, field, value)
  raise "Cannot append terms query to #{value} which is not an array" unless value.is_a?(Array)
  {
    nested: {
      path: path,
      query: {
        terms: {
          field => value
        }
      }
    }
  }
end

.get_query_bool_structureObject

returns query bool structure



176
177
178
179
180
181
182
183
184
185
# File 'lib/elastic_search_query.rb', line 176

def self.get_query_bool_structure
  {
    query:{
      bool: {
        filter:{
        }
      }
    }
  }
end

.get_range_query(field, from, to) ⇒ Object

returns range query



138
139
140
141
142
143
144
145
146
147
# File 'lib/elastic_search_query.rb', line 138

def self.get_range_query field, from, to
  q = {
    :range=> {
      field => {}
    }
  }
  q[:range][field][:from] = from if from.present?
  q[:range][field][:to] = to if to.present?
  return q
end

.get_reverse_nested_aggs(name, aggregations) ⇒ Object

returns a reverse nested structure



230
231
232
233
234
235
236
237
# File 'lib/elastic_search_query.rb', line 230

def self.get_reverse_nested_aggs name, aggregations
  {
    name => {
      "reverse_nested": {},
      "aggs": aggregations
    }
  }
end

.get_script_score_function_structureObject



399
400
401
402
403
404
405
406
407
408
# File 'lib/elastic_search_query.rb', line 399

def self.get_script_score_function_structure
  return {
    script_score: {
        script: {
            params: {},
            inline: ''
        }
    }
  }
end

.get_sort_subquery(sort_fields = []) ⇒ Object

used to append sort query so that the result is sorted based on the sort_fields provided



189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/elastic_search_query.rb', line 189

def self.get_sort_subquery sort_fields=[]
    raise "Cannot append sort query which is not an array" unless sort_fields.is_a?(Array)
    sort = []
    sort_fields.each do |field|
      if field.is_a? Hash
        field.each do |key, order|
          next unless (order=="asc" || order=="desc")
          sort << {key => {"order" => order}}
        end
      elsif (field.is_a? String) || (field.is_a? Symbol)
        sort << field.to_s
      end
    end
    return sort
end

.get_term_boost_query(field, value, boost) ⇒ Object

term boost query



98
99
100
101
102
103
104
105
106
107
# File 'lib/elastic_search_query.rb', line 98

def self.get_term_boost_query field, value, boost
  {
    :term => {
      field => {
        :value => value,
        :boost => boost
      }
    }
  }
end

.get_term_filter_query(field, value, cache_flag = false) ⇒ Object

term filter query



89
90
91
92
93
94
95
# File 'lib/elastic_search_query.rb', line 89

def self.get_term_filter_query(field, value, cache_flag = false)
  {
    term: {
      field => value
    }
  }
end

.get_terms_aggregation_structure(name, field_name, include_array = [], script = "", size = nil) ⇒ Object



239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/elastic_search_query.rb', line 239

def self.get_terms_aggregation_structure name, field_name, include_array = [], script = "", size = nil
  query = {
    name => {
      terms: {
        field: field_name
      }
    }
  }
  query[name][:terms][:include] = include_array if include_array.present?
  if script.present?
    query[name][:terms].delete(:field)
    query[name][:terms][:script] = script
  end
  if size.present? 
    size = 1  if size == 0 #size 0 is not supported since ES 5
    query[name][:terms][:size] = size
  end
  query
end

.get_terms_filter_query(field, value) ⇒ Object

returns terms_filter_query



110
111
112
113
114
115
116
117
# File 'lib/elastic_search_query.rb', line 110

def self.get_terms_filter_query(field, value)
    raise "Cannot append terms query to #{value} which is not an array" unless value.is_a?(Array)
    {
      terms: {
        field => value
      }
    }
end

.get_terms_structure_with_aggregation(name, field_name, aggregation, include_array = [], script = "") ⇒ Object

constructs an aggregation structure based on field_name provided this dynamically builds buckets on the basis of field_name and provides the aggregations accordingly if field_name = genre and genre has values (rock, jazz, thrash metal), then aggregations will be based on these three genres

Parameters:

  • name (String)

    name of the aggregation

  • field_name (String)

    on which aggregation is to be performed

  • aggregation (Array)

    specifying aggregations

  • include_array (Array) (defaults to: [])

    specifying conditions on the field_name

  • script (Hash) (defaults to: "")

    , to be executed for aggregation



351
352
353
354
355
# File 'lib/elastic_search_query.rb', line 351

def self.get_terms_structure_with_aggregation name, field_name, aggregation, include_array = [], script = ""
  query = get_terms_aggregation_structure name, field_name, include_array, script
  query[name][:aggs] = aggregation
  return query
end

.get_top_hits_aggregations(name, size, sort, source = []) ⇒ Object

constraucts a top_hits structure this aggregator is intended to be used as a sub aggregator, so that the top matching documents can be aggregated per bucket

Parameters:

  • name (String)

    name of the aggregation

  • size (Integer)

    specifying number of top results to be returned

  • sort (Array)

    specifying the sorting order

  • source (Array) (defaults to: [])

    specifying the data fields to be present in the result



212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/elastic_search_query.rb', line 212

def self.get_top_hits_aggregations name, size, sort, source = []
  query = {
    name => {
      "top_hits": {
        "size": size
      }
    }
  }.with_indifferent_access
  query[name]["top_hits"]["sort"] = sort if sort.present?
  if source.present?
    query[name]["top_hits"]["_source"] = {
      "include": source
    }
  end
  query
end

.merge_bool_query(main_query, query) ⇒ Object

merges bool queries into the main_query

Parameters:

  • main_query (Hash)

    query to be modified

  • query (Hash)

    query whose bool params are to be merged in main_query



450
451
452
453
454
455
456
457
458
459
460
# File 'lib/elastic_search_query.rb', line 450

def self.merge_bool_query(main_query, query)
  query[:bool].each { |key, val|
    if main_query[:bool].key?(key)
      main_query[:bool][key] = Array.new([main_query[:bool][key]]) << val
      main_query[:bool][key].flatten!
    else
      main_query[:bool][key] = val
    end
  }
  main_query
end

.percentile_aggregation(aggregation_name, field, percentile_points) ⇒ Object

calculates percentiles based on the field and provided percentile points

Parameters:

  • aggregation_name (String)

    name of the aggregation

  • field (String)

    on which aggregation is to be performed

  • percentile_points (Array)

    percentile points in which we are interested



316
317
318
319
320
321
322
323
324
325
# File 'lib/elastic_search_query.rb', line 316

def self.percentile_aggregation aggregation_name, field, percentile_points
  {
    aggregation_name.intern => {
      :percentiles => {
        :field => field,
        :percents => percentile_points
      }
    }
  }
end

.range_aggregation(aggregation_name, field, ranges) ⇒ Object

used for bucketing the response based on the field and range provided sample range [{ “to” : 100.0 },{ “from” : 100.0, “to” : 200.0 },{ “from” : 200.0 }]

Parameters:

  • aggregation_name (String)

    name of the aggregation

  • field (String)

    on which aggregation is to be performed

  • ranges (Array)

    specifying ranges



332
333
334
335
336
337
338
339
340
341
# File 'lib/elastic_search_query.rb', line 332

def self.range_aggregation aggregation_name, field, ranges
  {
    aggregation_name.intern => {
      :range => {
        :field => field,
        :ranges => ranges
      }
    }
  }
end

.script_scoring_query(query, functions, boost_mode = "replace") ⇒ Object

to modify the score of documents that are retrieved by a query

Parameters:

  • query (Hash)
  • functions (Array)

    specifying the conditions and scores

  • boost_mode (String) (defaults to: "replace")

    specifying boost_mode (replace, multiply)



387
388
389
390
391
392
393
394
395
396
397
# File 'lib/elastic_search_query.rb', line 387

def self.script_scoring_query(query, functions, boost_mode="replace")
  return query.except(:query).merge({
    query: {
      function_score: {
        query: query[:query],
        functions: functions,
        boost_mode: boost_mode
      }
    }
  })
end