Date-boosting Solr / Drupal search results

By replacing Drupal's core search with Solr, it's possible to gain very fine control of the results. Not only is Solr very flexble, but the apachesolr module is generous with its hooks. One potential use is boosting the score based on dates, so that recent documents receive a higher relevancy score. We've used this for the L.A. Philharmonic's ticket calendar to help patrons find upcoming events.

First, look up the name of the field you need in the schema browser (http://localhost:8983/solr/admin/ for a local install). You should be able to locate it based on the machine name of your Drupal field (assuming the index is up-to-date).

hook_apachesolr_query_alter()

Next, drop this hook in a custom module (note this is for Drupal 7). Substitute your field's name in for dm_field_date.

/**
 * Implements hook_apachesolr_query_alter().
 */
function hook_search_apachesolr_query_alter(DrupalSolrQueryInterface $query) {
  $query->addParam('bf', array('freshness' =>
    'recip(abs(ms(NOW/HOUR,dm_field_date)),3.16e-11,1,.1)'
  ));
}

Fine-tuning

This function will apply a +10 boost to a document with today's date, tapering off to about +1 after a year. To write your own boost function, consult the Solr Wiki page on FunctionQuery. Note there are no spaces in the function queries! Choosing the constants can feel a bit blind, so visualizing the function on Wolfram Alpha helps (the x-axis is in milliseconds):

Filed under:

Comments

Hi Dylan,

Great job doing all of this with Apache Solr. As one of the recent contributers of the project I really enjoy these kind of customizations that make it possible to create a super search experience.
I'd also love to hear what you have been struggling with so we can make it even better!

Hi Dylan,

I really liked this post. I'm a community curator at DZone.com and was wondering if you'd be interested in having some of your work featured on our site. If so, please contact me for more information.

Thanks and keep up the great work!

Chris

Thanks very much Dylan, I was struggling with trying to figure out how to do this in search_api and your post got me over the line.
For a solr based search_api implementation my code ended up looking like:

function mymodule_search_api_solr_query_alter(&$call_args, SearchApiQueryInterface $query) {
  $call_args['params']['bf'][] = 'recip(abs(ms(NOW/HOUR,ds_publication_date)),4.16e-11,4,.4)';
}

Can you tell me what having a boost score in the standard notation for DisMaxQParserPlugin after the recip function would do? If I changed the function to:

function mymodule_search_api_solr_query_alter(&$call_args, SearchApiQueryInterface $query) {
  $call_args['params']['bf'][] = 'recip(abs(ms(NOW/HOUR,ds_publication_date)),4.16e-11,4,.4)^10';
}

Would the maximum score then become 20 or is this the correct way of making it 10?

Thank you very much. Keep up the good work!

Thanks for this - I've been catching up with some Drupal8 search_api and search_api_solr-dev updates today (needs -dev due to an API change inside search_api).
It seems that the 'bf' parameter was having no effect for me, but one called 'boost' would.
Current code that is working for me:
**beehive_search.module**

<?php
/**
 * Favour more recent content in search results.
 *
 * This sends a 'boost' function that uses date math to demote older stuff
 * using an exponential age function.
 *
 * Details about the diff between bf and 'boost' function in
 * https://nolanlawson.com/2012/06/02/comparing-boost-methods-in-solr/
 *
 * Explanation of the function:
 * https://www.metaltoad.com/blog/date-boosting-solr-drupal-search-results
 *
 * OLD howto:
 * https://www.drupal.org/node/2194055
 *
 * Works in D8 & Current Solr:
 * https://www.drupal.org/node/2823538
 *
 *
 * Implements hook_search_api_solr_query_alter().
 */
function beehive_search_search_api_solr_query_alter(\Solarium\QueryType\Select\Query\Query $solarium_query, \Drupal\search_api\Query\QueryInterface $query) {
  // 'boost' is a solr keyword.
  // Our ds_field_issue_date is specific to the beehive site.
  $solarium_query->addParam(
    'boost',
    'recip(abs(ms(NOW/HOUR,ds_field_issue_date)),3.16e-11,1,.1)'
  );
}
?>

Add new comment

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>, <cpp>, <java>, <php>. The supported tag styles are: <foo>, [foo].
  • Web page addresses and email addresses turn into links automatically.
  • Lines and paragraphs break automatically.

Ready for transformation?