class Estella::Query

Attributes

params[R]
query[RW]

Constructs a search query for ES

Public Class Methods

new(params) click to toggle source
# File lib/estella/query.rb, line 7
def initialize(params)
  @params = params
  @query = {
    _source: false,
    query: { bool: { must: [{ match_all: {} }], must_not: [], filter: [] } },
    aggregations: {}
  }
  add_query
  add_filters
  add_excludes
  add_pagination
end

Public Instance Methods

exclude(filter) click to toggle source
# File lib/estella/query.rb, line 28
def exclude(filter)
  if query[:query][:function_score]
    query[:query][:function_score][:query][:bool][:must_not] << filter
  else
    query[:query][:bool][:must_not] << filter
  end
end
field_factors() click to toggle source
# File lib/estella/query.rb, line 46
def field_factors
  Estella::Analysis::DEFAULT_FIELD_FACTORS
end
must(filter) click to toggle source
# File lib/estella/query.rb, line 20
def must(filter)
  if query[:query][:function_score]
    query[:query][:function_score][:query][:bool][:filter] << filter
  else
    query[:query][:bool][:filter] << filter
  end
end
term_query_definition() click to toggle source
# File lib/estella/query.rb, line 36
def term_query_definition
  {
    multi_match: {
      type: 'most_fields',
      fields: term_search_fields,
      query: params[:term]
    }
  }
end

Private Instance Methods

add_excludes() click to toggle source
# File lib/estella/query.rb, line 122
def add_excludes
  exclude = params[:exclude]
  return unless exclude

  exclude.each do |k, v|
    exclude(term: { k => v })
  end
end
add_field_boost() click to toggle source
# File lib/estella/query.rb, line 80
def add_field_boost
  boost = params[:boost]
  return unless boost

  query[:query][:function_score][:field_value_factor] = {
    field: boost[:field],
    modifier: boost[:modifier],
    factor: boost[:factor]
  }

  max = boost[:max]
  return unless max

  query[:query][:function_score][:max_boost] = max
end
add_filters() click to toggle source
# File lib/estella/query.rb, line 111
def add_filters
  indexed_fields = params[:indexed_fields]
  return unless indexed_fields

  indexed_fields.each do |field, opts|
    next unless opts[:filter] && params[field]

    must term: { field => params[field] }
  end
end
add_pagination() click to toggle source
# File lib/estella/query.rb, line 52
def add_pagination
  query[:size] = params[:size] if params[:size]
  query[:from] = params[:from] if params[:from]
end
add_query() click to toggle source
# File lib/estella/query.rb, line 57
def add_query
  return unless params[:term] && params[:indexed_fields]

  add_term_query
end
add_term_query() click to toggle source

fulltext search across all string fields

# File lib/estella/query.rb, line 64
def add_term_query
  query[:query] = {
    function_score: {
      query: {
        bool: {
          must: term_query_definition,
          filter: [],
          must_not: []
        }
      }
    }
  }

  add_field_boost
end
term_search_fields() click to toggle source

search all analysed string fields by default boost them by factor if provided

# File lib/estella/query.rb, line 98
def term_search_fields
  params[:indexed_fields]
    .select { |_, opts| opts[:type].to_s == 'text' }
    .reject { |_, opts| opts[:analysis].nil? }
    .map do |field, opts|
      opts[:analysis].map do |analyzer|
        factor = field_factors[analyzer] * opts.fetch(:factor, 1.0)
        "#{field}.#{analyzer}^#{factor}"
      end
    end
    .flatten
end