Adding a Custom Sort to a Drupal Solr Search

We wanted to add a “sort by popularity” option on a Solr-driven search. Documentation for how to add a custom sort when using the Drupal Solr modules is hard to track down and there’s one other piece of the puzzle that I haven’t seen mentioned anywhere else.

1. Implement hook_apachesolr_index_document_build()

This tells Solr to add the field when it’s indexing (so you’ll have to rebuild the index once your module is ready). Example:

function custom_module_apachesolr_index_document_build(ApacheSolrDocument $document, $entity, $entity_type, $env_id)
  $document->addField('is_field_name', $value);
}

You’ll probably want to check the $entity object to see what you’re dealing with and only add when necessary. The “is_” prefix specifies the type – long in this case. Check your Solr schema.xml for available types.

2. Implement hook_apachesolr_query_prepare()

This tells Solr that we have another field available to sort by.

function custom_module_apachesolr_query_prepare($query) {

  $query->setAvailableSort('is_field_name', array(
    'title' => t('Field Title'),
    'default' => 'desc',
  ));

}

If Solr doesn’t know that your field is valid to sort by, it’ll default to score (relevancy). I found that this was happening because I needed to…

3. Make sure your module runs before the apachesolr module

This may have been necessary in our case because of how our page was built, or it might apply to everyone, it’s hard to say.

function custom_module_install(){

  db_query("
    UPDATE system SET weight =
      ((SELECT weight FROM (SELECT * FROM system) AS system_alias WHERE name = 'apachesolr') - 1)
    WHERE name = 'custom_module'");

}


This one was hard to track down, but the SolrBaseQuery::available_sorts property needs to contain all valid sorts and will only do so if the hook in 2 has already run.