Search API Solr sort by a field depending of value

Soumis par GoZ le lun 20/02/2017 - 09:01

Search API Solr sort by a field depending of value

With Drupal 7 and Search API + Search API Solr, i need to return content in top of results depending of another value.

Content indexed has 2 multiple fields list (or taxonomies like in example, whatever) with the same list: 'field_job' and 'field_best_job'. This is my example, but this can be converted by many other uses case.
First, my search is filtered by a facet on a field 'field_job' with value 'developer' and i want to put on top of results every contents which also have 'developer' value in the field 'field_best_job'.

We will not add a custom sort which will be hard to do, but using boost.

Altering search api solr query, we will boost results with 'developer' value in 'field_best_job'. This only works if you sort your results by relevance.


/**
 * Implements hook_search_api_solr_query_alter().
 */
function MYMODULE_search_api_solr_query_alter(array &$call_args, SearchApiQueryInterface $query) {
  // Alter query only on specific index search.
  if ($query->getIndex()->machine_name == 'MY_SEARCH_INDEX_NAME') {
    // Get current search value from field_job.
    if ($filter_job = _MYMODULE_query_get_filter($query->getFilter(), 'field_job:name')) {
      // Add Boost Query param to solr query on sm_field_best_job name with field_job value with 95 boost level.
      $call_args['params']['bq'] = 'sm_field_best_job$name:"' . $filter_job[1] . '"^95';
    }
  }
}

/**
 * Get filter from a SearchApiQueryFilter.
 *
 * @param \SearchApiQueryFilterInterface $filter
 *   Filter where to search.
 * @param string $filter_name
 *   Filter name to find.
 *
 * @return array
 *   Filter array with name and value or empty.
 */
function _MYMODULE_query_get_filter(SearchApiQueryFilterInterface $filter, $filter_name) {
  foreach ($filter->getFilters() as $filter_search) {
    // Search in subfilters.
    if ($filter_search instanceof SearchApiQueryFilterInterface) {
      // If filter is found in deep search, return it.
      if ($filter_found = _MYMODULE_query_get_filter($filter_search, $filter_name)) {
        return $filter_found;
      }
    }
    // Return filter if name is matching.
    if (is_array($filter_search) && $filter_search[0] == $filter_name) {
      return $filter_search;
    }
  }

  return array();
}

source: http://www.unimitysolutions.com/blog/modify-apache-solr-queries-drupal