Sorting by Specific Fields with Apache Solr
Recently I had to configure an Apache Solr search page to have the results sorted by a date field. We’re using the apachesolr module, which has a number of useful hooks, two of which we’ll use to accomplish this custom sort.
If you browse to Administration » Reports » Apache Solr search index you will see a list of the indexed fields (example shown below). Most of the documentation I’ve seen out there regarding apachesolr sorting says you can use $query->setAvailableSort() and $query->setSolrSort() within an implementation of hook_apachesolr_query_prepare() , but there is at least one caveat: the field you want to sort on must be a single-value field! Here’s a look at the field list on the site I’m working on:
Take note of the ds and dm prefixes on the bottom two fields. The d represents “date” (the type of field these are), m represents “multiple” or “multi-value”, and the s represents a single value. So, as you might have guessed, we have to do a little more work to sort by dm_field_research_pubdate (because it’s a multi-value field).
You can find in-depth explanations elsewhere, so I’ll just show you the end result here.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
/** * Implements hook_apachesolr_index_document_build_node(). */ function mymodule_apachesolr_index_document_build_node(ApacheSolrDocument $document, $entity, $entity_type) { if ($entity->type == 'research') { // Add the start date of the field_research_pubdate field as a sort field to the SOLR index // because we cannot use dm_field_research_pubdate (date multiple; must be single) from // admin/reports/apachesolr/acquia_search_server_1 $research_date = field_get_items('node', $entity, 'field_research_pubdate'); if (!empty($research_date)) { $document->addField('ds_field_research_pubdate', apachesolr_date_iso(strtotime($research_date[0]['value']))); } } } /** * Implements hook_apachesolr_query_prepare(). */ function mymodule_apachesolr_query_prepare($query) { // Add Publication Date sort to the faculty-research search if (arg(0) == 'faculty-research') { // Add the new field as a sort option $query->setAvailableSort('ds_field_research_pubdate', array( 'title' => t('Research Publication Date'), 'default' => 'desc', )); // Sort on our new field $query->setSolrSort('ds_field_research_pubdate', 'desc'); } } |
I should point out that you can use whatever logic you want within your hook_apachesolr_index_document_build_ENTITY_TYPE implementation. In the example above I’m just getting the second value in the date field. You could, for example, implode() an array here, or concatenate some fields into a single value. The options are abundant.
While we’re at it, if we think we’ll need this field in the output (perhaps our theme needs to make use of the field?) we’d add an additional hook implementation:
1 2 3 4 5 6 7 8 9 |
/** * Implements hook_apachesolr_query_alter(). */ function mymodule_apachesolr_query_alter($query) { if (arg(0) == 'faculty-research') { // Make this field available within template_preprocess_search_result() $query->addParam('fl','ds_field_research_pubdate'); } } |
Don’t forget to re-index your search after implementing hook_apachesolr_index_document_build_node(). Also, you’ll probably want to clear your Drupal cache after making these changes.