class Trample::Backend::Searchkick

Public Class Methods

new(metadata, models) click to toggle source
# File lib/trample/backend/searchkick.rb, line 7
def initialize(metadata, models)
  @metadata = metadata
  @_models = models
end

Public Instance Methods

query!(conditions, aggregations) click to toggle source
# File lib/trample/backend/searchkick.rb, line 12
def query!(conditions, aggregations)
  results = resume_or_execute(conditions, aggregations)

  {
    total:     results.total_count,
    took:      results.response['took'],
    results:   results.results,
    scroll_id: results.response['_scroll_id']
  }
end
resume_or_execute(conditions, aggregations) click to toggle source

There are 3 types of searches

  • A) Vanilla

  • B) Vanilla, but tell ES we are scrolling

  • C) A scroll search, using the scroll_id from B

# File lib/trample/backend/searchkick.rb, line 28
def resume_or_execute(conditions, aggregations)
  payload = build_payload(conditions, aggregations, @metadata, @_models)
  query = ::Searchkick::Query.new(@_models.first, keywords(conditions), payload)

  response = if @metadata.scroll_id
    resume_search(@metadata.scroll_id)
  else
    execute_search(query)
  end
  results = query.handle_response(response)
  parse_response_aggs!(results.aggs, aggregations) if results.response.has_key?('aggregations')
  results
end

Private Instance Methods

_sorts(metadata) click to toggle source
# File lib/trample/backend/searchkick.rb, line 114
def _sorts(metadata)
  metadata.sort.map do |s|
    {s.att => s.dir}
  end
end
build_condition_clauses(conditions, aggregations) click to toggle source

N.B. aggs and conditions could hit same key

# File lib/trample/backend/searchkick.rb, line 80
def build_condition_clauses(conditions, aggregations)
  {}.tap do |clauses|
    aggregations.each do |agg|
      clauses.merge!(agg.to_query) if agg.selections?
    end
    conditions.each_pair do |name, condition|
      next if condition.name == :keywords
      merge_clause(clauses, condition.to_query) unless condition.blank?
    end
  end
end
build_payload(conditions, aggregations, metadata, models) click to toggle source
# File lib/trample/backend/searchkick.rb, line 72
def build_payload(conditions, aggregations, metadata, models)
  clauses = build_condition_clauses(conditions, aggregations)
  query   = searchkick_payload(conditions[:keywords], clauses, metadata, aggregations)
  query.merge!(index_name: models.map { |m| m.searchkick_index.name }) if models.length > 1
  query
end
keywords(conditions) click to toggle source
# File lib/trample/backend/searchkick.rb, line 62
def keywords(conditions)
  condition = conditions[:keywords]
  value = condition.values.first if condition and condition.values
  if ![nil, ''].include?(value)
    value
  else
    '*'
  end
end
merge_clause(clauses, clause) click to toggle source
# File lib/trample/backend/searchkick.rb, line 92
def merge_clause(clauses, clause)
  if clause[:or]
    clauses[:or] ||= []
    clauses[:or] << clause[:or]
  else
    clauses.merge!(clause)
  end
end
parse_response_aggs!(response_aggs, search_aggs) click to toggle source
# File lib/trample/backend/searchkick.rb, line 120
def parse_response_aggs!(response_aggs, search_aggs)
  response_aggs.each_pair do |key, payload|
    agg = search_aggs.find { |a| a.name.to_sym == key.to_sym }
    payload['buckets'].each do |response_bucket|
      bucket = agg.find_or_initialize_bucket(response_bucket['key'])
      bucket.count = response_bucket['doc_count']
    end
  end
end
raw_search_params(query, scroll: false) click to toggle source
# File lib/trample/backend/searchkick.rb, line 54
def raw_search_params(query, scroll: false)
  query.params.tap do |search_params|
    if scroll
      search_params[:scroll] = '5m'
    end
  end
end
searchkick_payload(keywords, clauses, metadata, aggs) click to toggle source
# File lib/trample/backend/searchkick.rb, line 101
def searchkick_payload(keywords, clauses, metadata, aggs)
  payload = {
    where:    clauses,
    order:    _sorts(metadata),
    page:     metadata.pagination.current_page,
    per_page: metadata.pagination.per_page,
    aggs:     aggs.map(&:name),
    load:     false
  }
  payload[:fields] = keywords.fields if keywords and !keywords.fields.empty?
  payload
end