module Blacklight::Solr::Response::Facets

Public Instance Methods

aggregations() click to toggle source

Get all the Solr facet data (fields, queries, pivots) as a hash keyed by both the Solr field name and/or by the blacklight field name

# File lib/blacklight/solr/response/facets.rb, line 112
def aggregations
  @aggregations ||= default_aggregations.merge(facet_field_aggregations).merge(facet_query_aggregations).merge(facet_pivot_aggregations).merge(json_facet_aggregations)
end
facet_counts() click to toggle source
# File lib/blacklight/solr/response/facets.rb, line 116
def facet_counts
  @facet_counts ||= self['facet_counts'] || {}
end
facet_fields() click to toggle source

Returns the hash of all the facet_fields (ie: { ‘instock_b’ => [‘true’, 123, ‘false’, 20] }

# File lib/blacklight/solr/response/facets.rb, line 121
def facet_fields
  @facet_fields ||= begin
    val = facet_counts['facet_fields'] || {}

    # this is some old solr (1.4? earlier?) serialization of facet fields
    if val.is_a? Array
      val.to_h
    else
      val
    end
  end
end
facet_pivot() click to toggle source

Returns all of the facet queries

# File lib/blacklight/solr/response/facets.rb, line 140
def facet_pivot
  @facet_pivot ||= facet_counts['facet_pivot'] || {}
end
facet_queries() click to toggle source

Returns all of the facet queries

# File lib/blacklight/solr/response/facets.rb, line 135
def facet_queries
  @facet_queries ||= facet_counts['facet_queries'] || {}
end
merge_facet(name:, value:, hits: nil) click to toggle source

Merge or add new facet count values to existing response

# File lib/blacklight/solr/response/facets.rb, line 145
def merge_facet(name:, value:, hits: nil)
  if dig('facet_counts', 'facet_fields', name)
    self['facet_counts']['facet_fields'][name] << value << hits
  else
    self['facet_counts']['facet_fields'][name] = [value, hits]
  end
end

Private Instance Methods

construct_json_nested_facet_fields(bucket, parent_fq = {}) click to toggle source
# File lib/blacklight/solr/response/facets.rb, line 292
def construct_json_nested_facet_fields(bucket, parent_fq = {})
  bucket.select { |_, nested| nested.is_a?(Hash) && nested.key?('buckets') }.map do |facet_field_name, nested|
    nested['buckets'].map do |subbucket|
      i = Blacklight::Solr::Response::Facets::FacetItem.new(field: facet_field_name, value: subbucket['val'], hits: subbucket['count'], fq: parent_fq, data: subbucket)

      i.items = construct_json_nested_facet_fields(subbucket, parent_fq.merge(key => subbucket['val'])) if has_json_nested_facets?(subbucket)
      i
    end
  end.flatten
end
construct_pivot_field(lst, parent_fq = {}) click to toggle source

Recursively parse the pivot facet response to build up the full pivot tree

# File lib/blacklight/solr/response/facets.rb, line 284
def construct_pivot_field lst, parent_fq = {}
  items = Array(lst[:pivot]).map do |i|
    construct_pivot_field(i, parent_fq.merge({ lst[:field] => lst[:value] }))
  end

  Blacklight::Solr::Response::Facets::FacetItem.new(value: lst[:value], hits: lst[:count], field: lst[:field], items: items, fq: parent_fq)
end
default_aggregations() click to toggle source

@return [Hash] establish a null object pattern for facet data look-up, allowing

the response and applied parameters to get passed through even if there was no
facet data in the response
# File lib/blacklight/solr/response/facets.rb, line 158
def default_aggregations
  @default_aggregations ||= begin
    h = Hash.new { |key| null_facet_field_object(key) }
    h.with_indifferent_access
  end
end
facet_field_aggregations() click to toggle source

Convert Solr’s facet_field response into a hash of Blacklight::Solr::Response::Facet::FacetField objects

# File lib/blacklight/solr/response/facets.rb, line 192
def facet_field_aggregations
  list_as_hash(facet_fields).each_with_object({}) do |(facet_field_name, values), hash|
    items = values.map do |value, hits|
      i = FacetItem.new(value: value, hits: hits)

      # legacy solr facet.missing serialization
      if value.nil?
        i.label = I18n.t(:"blacklight.search.fields.facet.missing.#{facet_field_name}", default: [:'blacklight.search.facets.missing'])
        i.fq = "-#{facet_field_name}:[* TO *]" # this explicit fq is deprecated; the missing attribute below is a better thing to check for this case
        i.value = Blacklight::SearchState::FilterField::MISSING
        i.missing = true
      end

      i
    end

    options = facet_field_aggregation_options(facet_field_name)
    facet_field = FacetField.new(facet_field_name, items, options.merge(response: self))

    if values[nil]
      facet_field.missing = items.find(&:missing)
    end

    hash[facet_field_name] = facet_field

    # alias all the possible blacklight config names..
    blacklight_config.facet_fields.select { |_k, v| v.field == facet_field_name }.each_key do |key|
      hash[key] = hash[facet_field_name]
    end if blacklight_config && !blacklight_config.facet_fields[facet_field_name]
  end
end
facet_pivot_aggregations() click to toggle source

Convert Solr’s facet_pivot response into a hash of Blacklight::Solr::Response::Facet::FacetField objects

# File lib/blacklight/solr/response/facets.rb, line 265
def facet_pivot_aggregations
  facet_pivot.each_with_object({}) do |(field_name, values), hash|
    next unless blacklight_config && !blacklight_config.facet_fields[field_name]

    items = values.map do |lst|
      construct_pivot_field(lst)
    end

    # alias all the possible blacklight config names..
    blacklight_config.facet_fields.select { |_k, v| v.pivot && v.pivot.join(",") == field_name }.each_key do |key|
      facet_field = Blacklight::Solr::Response::Facets::FacetField.new key, items, response: self

      hash[key] = facet_field
    end
  end
end
facet_query_aggregations() click to toggle source

Aggregate Solr’s facet_query response into the virtual facet fields defined in the blacklight configuration

# File lib/blacklight/solr/response/facets.rb, line 227
def facet_query_aggregations
  return {} unless blacklight_config

  blacklight_config.facet_fields.select { |_k, v| v.query }.each_with_object({}) do |(field_name, facet_field), hash|
    salient_facet_queries = facet_field.query.map { |_k, x| x[:fq] }
    items = facet_queries.select { |k, _v| salient_facet_queries.include?(k) }.reject { |_value, hits| hits.zero? }.map do |value, hits|
      salient_fields = facet_field.query.select { |_key, val| val[:fq] == value }
      key = ((salient_fields.keys if salient_fields.respond_to? :keys) || salient_fields.first).first
      Blacklight::Solr::Response::Facets::FacetItem.new(value: key, hits: hits, label: facet_field.query[key][:label])
    end

    items += facet_query_aggregations_from_json(facet_field)

    items = items.sort_by(&:hits).reverse if facet_field.sort && facet_field.sort.to_sym == :count

    facet_field = Blacklight::Solr::Response::Facets::FacetField.new field_name, items, response: response

    hash[field_name] = facet_field
  end
end
facet_query_aggregations_from_json(facet_field) click to toggle source
# File lib/blacklight/solr/response/facets.rb, line 248
def facet_query_aggregations_from_json(facet_field)
  return [] unless self['facets']

  salient_facet_queries = facet_field.query.map { |_k, x| x[:fq] }

  relevant_facet_data = self['facets'].select { |k, _v| salient_facet_queries.include?(k) }.reject { |_key, data| data['count'].zero? }

  relevant_facet_data.map do |key, data|
    salient_fields = facet_field.query.select { |_key, val| val[:fq] == key }
    facet_key = ((salient_fields.keys if salient_fields.respond_to? :keys) || salient_fields.first).first
    Blacklight::Solr::Response::Facets::FacetItem.new(value: facet_key, hits: data[:count], label: facet_field.query[facet_key][:label])
  end
end
has_json_nested_facets?(bucket) click to toggle source
# File lib/blacklight/solr/response/facets.rb, line 303
def has_json_nested_facets?(bucket)
  bucket.any? { |_, nested| nested.is_a?(Hash) && nested.key?('buckets') }
end
json_facet_aggregations() click to toggle source
# File lib/blacklight/solr/response/facets.rb, line 307
def json_facet_aggregations
  return {} unless self['facets']

  self['facets'].each_with_object({}) do |(facet_field_name, data), hash|
    next if facet_field_name == 'count'

    items = (data['buckets'] || []).map do |bucket|
      i = Blacklight::Solr::Response::Facets::FacetItem.new(value: bucket['val'], hits: bucket['count'], data: bucket)

      i.items = construct_json_nested_facet_fields(bucket, facet_field_name => bucket['val']) if has_json_nested_facets?(bucket)

      i
    end

    options = facet_field_aggregation_options(facet_field_name).merge(data: data, response: self)
    facet_field = FacetField.new(facet_field_name, items, options)

    facet_field.missing = Blacklight::Solr::Response::Facets::FacetItem.new(
      hits: data.dig('missing', 'count'),
      data: data['missing']
    ) if data['missing']

    hash[facet_field_name] = facet_field
  end
end
list_as_hash(solr_list) click to toggle source

Convert Solr responses of various json.nl flavors to

# File lib/blacklight/solr/response/facets.rb, line 172
def list_as_hash solr_list
  # map
  if solr_list.values.first.is_a? Hash
    solr_list
  else
    solr_list.transform_values do |values|
      if values.first.is_a? Array
        # arrarr
        values.to_h
      else
        # flat
        values.each_slice(2).to_a.to_h
      end
    end
  end
end
null_facet_field_object(key) click to toggle source

@return [Blacklight::Solr::Response::FacetField] a “null object” facet field

# File lib/blacklight/solr/response/facets.rb, line 166
def null_facet_field_object(key)
  Blacklight::Solr::Response::FacetField.new(key, [], facet_field_aggregation_options(key).merge(response: self))
end