Skip to content

Extending or Modifying Blacklight Search Behavior

Justin Coyne edited this page Nov 10, 2021 · 30 revisions

Extending or Modifying Blacklight Search Behavior

Solr parameters used by a given request can come from several different places.

  • Solr request handler: solrconfig.xml in your solr config
  • Application logic: logic in the BL rails app itself

Solr request handler

The Solr Request Handlers may be configured in the solrconfig.xml and are baked into the request handler itself. Depending on how you have blacklight configured, your app may be using the same Solr request handler for all searches, or may be using different request handlers for different "search fields".

The request handler is often set up with default parameters:

  <requestHandler name="standard" class="solr.SearchHandler" >
     <lst name="defaults">
       <str name="echoParams">explicit</str>
       <str name="rows">10</str> 
       <str name="fl">*</str>   
       <str name="facet">true</str>
       <str name="facet.mincount">1</str>
       <str name="facet.limit">30</str> 
       <str name="facet.field">access_facet</str>
       <str name="facet.field">author_person_facet</str>
       <str name="facet.field">author_other_facet</str>
       <str name="facet.field">building_facet</str>
       <str name="facet.field">callnum_1_facet</str>
       <str name="facet.field">era_facet</str>
       <str name="facet.field">format</str>
       <str name="facet.field">geographic_facet</str>
       <str name="facet.field">language</str>
       <str name="facet.field">pub_date_group_facet</str>
       <str name="facet.field">topic_facet</str>
     </lst>
  </requestHandler>

Configuration

The default application logic (explained below) looks in configuration for things like the name of a the solr request handler to use, and default request parameters to send on every solr search request (or with every request from a certain blacklight search type/field). An example getting started configuration is generally installed into your app when you install Blacklight at ./app/controllers/catalog_controller.rb.

Application logic

The logic Blacklight uses to determine how to map user-supplied parameters into Solr request parameters for a given application request is in the #processed_parameters method in the SearchBuilder class.

SearchBuilder uses an ordered list of methods, called a processor_chain, that use the supplied user parameters and add, remove, or modify the Solr request parameters.

At the end of processing, the resulting output builds a RSolr request. RSolr will convert the hash into query parameters for a Solr request.

The default Blacklight::Solr::SearchBuilder logic is intended to handle common mapping using simple configuration options from the controller and the user-supplied URL parameters.

  • blacklight_config.default_solr_params
    • Default params sent to solr with every search, including the default :qt param, which determines which Solr request handler will be targetted. Some people like to use solrconfig.xml request handler defaults exclusively, and include only a :qt here; others find it more convenient to specify some defaults at the application level here.
  • blacklight_config.search_field
    • Each search field will be presented in a select menu in the BL user interface search box. These 'search fields' don't neccesarily correspond 1-to-1 with Solr fields. What they instead correspond to is Solr parameter over-rides that will be used for this BL UI search field. Those over-rides are present here.
    • You could simply chose a different :qt Solr request handler for each search field, which has it's own default parameters in the sorlconfig.xml. This is what we started out doing with Solr, but found it led to much duplication of information in solrconfig.xml.
    • You can continue using the same Solr request handler, but simply specify different parameters which will be included in the http query string sent to Solr here, with the :solr_parameters key. This works fine, but some people don't like how it makes your Solr requests much longer/more complex in the Solr logs; and/or they prefer to control this Solr side instead of Application side.
    • For the best of both worlds, although it's a bit confusing at first, you can use the :solr_local_parameters key to have parameters supplied to Solr using the Solr LocalParams syntax, which means you can use "parameter dereferencing" with dollar-sign-prefixed references to variables defined in solrconfig.xml request handler. This is what the current example BL setup does.

So the default implementation of SearchBuilder takes these configured parameters, combines them with certain query parameters from the current users HTTP request to the BL app, and prepares a query that will be sent to solr. For common use patterns, this is all you need.

But sometimes you want to add some custom logic to map to solr parameters in different ways. Typically, this is used to support a new UI feature of some kind.

Extending the SearchBuilder

To add new search behaviors (e.g. authorization controls, pre-parsing query strings, etc), the easiest route is to add additional steps to the SearchBuilder model generated into your application's ./app/models directory.

First, you should create the method. The SearchBuilder will call this method with a single parameter, which your method will mutate to add additional query parameters.

# ./app/models/search_builder.rb

class SearchBuilder < Blacklight::SearchBuilder
  include Blacklight::Solr::SearchBuilderBehavior
  
  # @param [Hash] solr_parameters a hash of parameters to be sent to Solr (via RSolr)
  def show_only_public_records(solr_parameters)
    # add a new solr facet query ('fq') parameter that limits results to those with a 'public_b' field of 1 
    solr_parameters[:fq] ||= []
    solr_parameters[:fq] << 'public_b:1'
  end
end

From the step, you can also access several instance-level methods, including:

  • blacklight_config, the blacklight catalog configuration
  • blacklight_params, containing the user-provided URL parameters

Then, you should add this step to the .default_processor_chain for the SearchBuilder, either at the beginning of the list (to set default parameters) or at the end of the list (to force particular parameters). Because .default_processor_chain is just an ordinary array, you may perform any normal array operation (e.g. push/pop/delete/insert) to customize the parameter generation to meet your needs.

You can add custom .default_processor_chain steps within your SearchBuilder by adding a Symbol with the name of a method you wish to use, e.g.:

# ./app/models/search_builder.rb

class SearchBuilder < Blacklight::SearchBuilder
  include Blacklight::Solr::SearchBuilderBehavior
  self.default_processor_chain += [:show_only_public_records]

  # ...
  def show_only_public_records(solr_parameters) # ...
end

Suppressing search results

You can configure your solrconfig.xml to not show results based on fields in your solr document. For example, if you have a solr boolean field such as show_b, you can suppress any records that have this field present. To do so, add:

<lst name="appends"><str name="fq">-show_b:["" TO *]</str></lst>

to the request handler in your solrconfig.xml file. If you would like this to be for standard solr searches, add the above line to this request handler:

<requestHandler name="search" class="solr.SearchHandler" default="true">

By doing so, solr queries that use the "document" request handler will still give you any records with the show_b field, but solr queries with the "search" handler will not.

Clone this wiki locally