otwarchive-symphonyarchive/app/models/search/query_result.rb
2026-03-11 22:22:11 +00:00

130 lines
3.3 KiB
Ruby

class QueryResult
include Enumerable
attr_reader :klass, :response, :current_page, :per_page, :error, :notice
def initialize(model_name, response, options={})
@klass = model_name.classify.constantize
@response = response
@current_page = options[:page] || 1
@per_page = options[:per_page] || ArchiveConfig.ITEMS_PER_PAGE
@error = response[:error]
@notice = max_search_results_notice
end
def hits
response.dig('hits', 'hits')
end
def items
return [] if response[:error]
if @items.nil?
@items = klass.load_from_elasticsearch(hits, scopes: @scopes)
end
@items
end
def scope(*args)
@scopes ||= []
@scopes += args
@items = nil # reset the items in case we already loaded them
self # for chaining
end
def each(&block)
items.each(&block)
end
def empty?
items.empty?
end
def size
items.size
end
alias :length :size
def [](index)
items[index]
end
def to_ary
items
end
def load_tag_facets(type, info)
@facets[type] = []
buckets = info["buckets"]
ids = buckets.map { |result| result['key'] }
tags = Tag.where(id: ids).group_by(&:id)
buckets.each do |facet|
unless tags[facet['key'].to_i].blank?
@facets[type] << QueryFacet.new(facet['key'], tags[facet['key'].to_i].first.name, facet['doc_count'])
end
end
end
def load_collection_facets(info)
@facets["collections"] = []
buckets = info["buckets"]
ids = buckets.map { |result| result['key'] }
collections = Collection.where(id: ids).group_by(&:id)
buckets.each do |facet|
unless collections[facet['key'].to_i].blank?
@facets["collections"] << QueryFacet.new(facet['key'], collections[facet['key'].to_i].first.title, facet['doc_count'])
end
end
end
def load_facets(aggregations)
aggregations.each_pair do |term, results|
if Tag::TYPES.include?(term.classify) || term == "tag"
load_tag_facets(term, results)
elsif term == "collections"
load_collection_facets(results)
elsif term == "bookmarks"
load_facets(results["filtered_bookmarks"])
elsif term == "bookmarkable"
load_facets(results)
end
end
end
def facets
return if response["aggregations"].nil?
if @facets.nil?
@facets = {}
load_facets(response["aggregations"])
end
@facets
end
def total_pages
(total_entries / per_page.to_f).ceil rescue 0
end
# For pagination / fetching results.
def total_entries
[unlimited_total_entries, ArchiveConfig.MAX_SEARCH_RESULTS].min
end
def unlimited_total_entries
response.dig('hits', 'total', 'value') || 0
end
def offset
(current_page * per_page) - per_page
end
def max_search_results_notice
# if we're on the last page of search results AND there are more results than we can show
return unless current_page >= total_pages && unlimited_total_entries > total_entries
ActionController::Base.helpers.ts("Displaying %{displayed} results out of %{total}. Please use the filters or edit your search to customize this list further.",
displayed: total_entries,
total: unlimited_total_entries
).html_safe
end
end