class Krikri::QASearchIndex

Generates flattened Solr documents and manages indexing of DPLA MAP models.

@example

indexer = Krikri::QASearchIndex.new
agg = Krikri::Aggregation.new
doc = agg.to_jsonld['@graph'].first

indexer.add(doc)
indexer.commit

Attributes

solr[R]

Public Class Methods

new(opts = {}) click to toggle source

@param opts [Hash] options to pass to RSolr @see RSolr.connect

Calls superclass method Krikri::SearchIndex::new
# File lib/krikri/search_index.rb, line 161
def initialize(opts = {})
  # Override or append to default Solr options
  solr_opts = Krikri::Settings.solr.to_h.merge(opts)
  @solr = RSolr.connect(solr_opts)
  super(opts)
end

Public Instance Methods

add(doc) click to toggle source

Adds a single JSON document to Solr @param doc [Hash] A hash that complies with the Solr schema

# File lib/krikri/search_index.rb, line 174
def add(doc)
  solr.add solr_doc(doc)
end
bulk_add(docs) click to toggle source

Add multiple documents to Solr @param docs [Array] Array of hashes that comply with the Solr schema

# File lib/krikri/search_index.rb, line 191
def bulk_add(docs)
  solr.add(docs.map { |d| solr_doc(d) })
end
commit() click to toggle source

Commits changes to Solr, making them visible to new requests Should be run after self.add and self.delete Okay to add or delete multiple docs and commit them all with a single self.commit

# File lib/krikri/search_index.rb, line 214
def commit
  solr.commit
end
delete_by_id(id) click to toggle source

Deletes an item from Solr @param String or Array

# File lib/krikri/search_index.rb, line 198
def delete_by_id(id)
  solr.delete_by_id id
end
delete_by_query(query) click to toggle source

Deletes items from Solr that match query @param String or Array

# File lib/krikri/search_index.rb, line 205
def delete_by_query(query)
  solr.delete_by_query query
end
schema_keys() click to toggle source

Get field names from Solr schema in host application. Will raise exception if file not found. @return [Array]

# File lib/krikri/search_index.rb, line 230
def schema_keys
  schema_file = File.join(Rails.root, 'solr_conf', 'schema.xml')
  file = File.open(schema_file)
  doc = Nokogiri::XML(file)
  file.close
  doc.xpath('//fields/field').map { |f| f.attr('name') }
end
solr_doc(doc) click to toggle source

Converts JSON document into a Hash that complies with Solr schema @param [JSON] @return [Hash]

# File lib/krikri/search_index.rb, line 222
def solr_doc(doc)
  remove_invalid_keys(flat_hash(doc))
end
update_from_activity(activity) click to toggle source

@see Krikri::SearchIndex#update_from_activity

# File lib/krikri/search_index.rb, line 180
def update_from_activity(activity)
  fail "#{activity} is not an Activity" unless 
    activity.class == Krikri::Activity
  result = bulk_update_from_activity(activity)
  solr.commit
  result
end

Private Instance Methods

flat_hash(hash, keys = []) click to toggle source

Flattens a nested hash Joins keys with “_” and removes “@” symbols Example:

flat_hash( {"a"=>"1", "b"=>{"c"=>"2", "d"=>"3"} )
=> {"a"=>"1", "b_c"=>"2", "b_d"=>"3"}
# File lib/krikri/search_index.rb, line 246
def flat_hash(hash, keys = [])
  new_hash = {}

  hash.each do |key, val|
    new_hash[format_key(keys + [key])] = val unless
      val.is_a?(Array) || val.is_a?(Hash)
    new_hash.merge!(flat_hash(val, keys + [key])) if val.is_a? Hash

    if val.is_a? Array
      val.each do |v|
        if v.is_a? Hash
          new_hash.merge!(flat_hash(v, keys + [key])) do |key, f, s|
            Array(f) << s
          end
        else
          formatted_key = format_key(keys + [key])
          new_hash[formatted_key] =
            new_hash[formatted_key] ? (Array(new_hash[formatted_key]) << v) : v
        end
      end
    end
  end

  new_hash
end
format_key(keys) click to toggle source

Formats a key to match a field name in the Solr schema

Removes unnecessary special character strings that would require special treatment in Solr

@param Array

TODO: Revisit this to make it more generalizable

# File lib/krikri/search_index.rb, line 281
def format_key(keys)
  keys.join('_')
    .gsub('@', '')
    .gsub('http://www.geonames.org/ontology#', '')
    .gsub('http://www.w3.org/2003/01/geo/wgs84_pos#', '')
end
remove_invalid_keys(solr_doc) click to toggle source

Remove keys (ie. fields) that are not in the Solr schema. @param [Hash] @return [Hash]

# File lib/krikri/search_index.rb, line 292
def remove_invalid_keys(solr_doc)
  valid_keys = schema_keys
  solr_doc.delete_if { |key, _| !key.in? valid_keys }
end