Score:4

How can I add a boost to a search_api_solr query if a field has a value?

in flag

I'm trying to add a boost to a search api Solr query when a field has a particular value, e.g. when its nid = 123. Looking at Solr version 8.7 docs for boosting (my solr server version), this looks pretty straightforward. I just need to add a bq parameter like:

bq=nid:123^10

When I go to my Solr server's admin UI and add a query there - first checking the edismax parser checkbox, and then adding nid:123^10 into the bq field - I see results where my node with nid is at the top of the list (as I'd expect) with all other results after it. If I remove the option, my node with nid 123 is no longer at the top (also as I'd expect).

The search_api_solr module provides a hook to alter queries, hook_search_api_solr_query_alter(), where I can add my boost. (Side note, I've used this hook in the past to boost results based on a date basically as documented in this bkosborne comment.)

My understanding is that I should be able to implement something like:

function MY_MODULE_search_api_solr_query_alter(\Solarium\Core\Query\QueryInterface $solarium_query, \Drupal\search_api\Query\QueryInterface $query) {
  $solarium_query->addParam('bq', 'nid:123^10');
}

However, this has no impact on the relevancy scores of my results (I'm printing the relevancy score in my view and my node with nid 123 has the same score whether I add this parameter or not), nor, predictably, the order of the results.

What am I missing here?

Version Information:

  • Drupal core: 9.1.10
  • Search API: 8.x-1.19
  • Search API Solr: 4.1.12
  • Solr Server: 8.7.0

p.s. my nid field key is actually its_nid in the index, but I just used nid in this question for readability.

Score:5
in flag

I just needed to read more closely. All of the information is in the example code in the hook_search_api_solr_query_alter() documentation. (I think the format I was using may have been recommended for much older versions of search_api_solr, versions that are only recently no longer required on certain enterprise hosts.)

The simplest way to get this to work was to add the defType parameter to my query to tell it to use the edismax parser. This is documented in hook_search_api_solr_query_alter(). The following works:

function MY_MODULE_search_api_solr_query_alter(\Solarium\Core\Query\QueryInterface $solarium_query, \Drupal\search_api\Query\QueryInterface $query) {
  $solarium_query->addParam('bq', 'nid:123^10');
  // Avoid the conversion into a lucene parser expression, keep edismax.
  $solarium_query->addParam('defType', 'edismax');
}

However, reading the hook documentation, it shows an alternative approach that seems preferable:

function MY_MODULE_search_api_solr_query_alter(\Solarium\Core\Query\QueryInterface $solarium_query, \Drupal\search_api\Query\QueryInterface $query) {
  $boost_queries['special_node'] = [
    'query' => 'nid:123^10.0',
  ];
  $boost_queries['some_less_special_node'] = [
    'query' => 'nid:321^5.0',
  ];
  /** @var \Solarium\Component\EdisMax $edismax */
  $edismax = $solarium_query->getEDisMax();

  $edismax->addBoostQueries($boost_queries);

  // Avoid the conversion into a lucene parser expression, keep edismax.
  $solarium_query->addParam('defType', 'edismax');
}
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.