Drupal Solr Queries

If the default behavior of the apachesolr module doesn't cut it for you, you might want to perform some custom queries or add some custom fields to the index.

Basic queries:

<?php
$query = apachesolr_drupal_query('apachesolr');
$query->addFilter('bundle', 'article')
  ->addParam('rows', '100')
  ->addParam('start', '200')
  ->addParam('fl', 'entity_id'); // use the 'fl' param to restrict fields that are returned
 
// add a set of OR filters
$subfilterkeywords = array('subfilter1', 'subfilter2');
$subquery = apachesolr_drupal_query('apachesolr');
foreach ($subfilterkeywords as $subfilterkeyword) {
  $subsubquery = apachesolr_drupal_query('apachesolr');
  $subsubquery->addFilter('tm_field_some_custom_field', $subfilterkeyword);
  $subquery->addFilterSubQuery($subsubquery, 'OR');
}
$query->addFilterSubQuery($subquery);
 
$keywords = "keyword1 keyword2";
$response = $query->search($keywords);
?>

To add a custom field to the Solr index:
* note: String (ss_ and sm_) stores a word/sentence as an exact string without performing tokenization etc. Commonly useful for storing exact matches, e.g, for facetting.
Text (ts_ and tm_) typically performs tokenization, and secondary processing (such as lower-casing etc.). Useful for all scenarios when we want to match part of a sentence.

<?php
/**
 * Implements hook_apachesolr_index_document_build_ENTITY_TYPE()
 */
mymodule_apachesolr_index_document_build_node(ApacheSolrDocument $document, $entity, $entity_type){
  $lang = isset($entity->language) ? $entity->language : 'und';
  $my_custom_field = isset($entity->field_my_custom_field[$lang][0]['safe_value']) ? $entity->field_my_custom_field[$lang][0]['safe_value'] : FALSE;
  if ($my_custom_field) {
    $document->addField('ss_field_my_custom_field', $my_custom_field);
  }
}
?>

The methods below are good for inspecting the query in, for example, hook_apachesolr_query_alter or hook_apachesolr_query_prepare.

<?php
  sdpm($this->query);
  dpm($this->query->getContext());
  dpm($this->query->getFilters());
  dpm($this->query->getParams());
  dpm($this->query->getPath());
  dpm($this->query->getSolrParams());
?>

Finally, here is a class that sums it all up, including the ability to get the 'page' and 'solrsort' GET query parameter and use it to display a particular page of results sorted by a custom field:

<?php
 
/**
 * @file MyModuleQuery.php
 */
 
/**
 * Perform solr queries
 *   $query = new MyModuleQuery();
 *   $query->addFilter('bundle', 'article');
 *   $response = $query->doQuery();
 * @see apachesolr_drupal_query()
 */
class MyModuleQuery {
 
  private $query;
  private $solrsort;
  private $sortdirection;
  private $page;
 
  public function __construct() {
    $this->query = apachesolr_drupal_query('apachesolr');
    $this->query_params = drupal_get_query_parameters();
    $this->query->paperParams = array();
    $this->solrsort = isset($this->query_params['solrsort']) ? $this->query_params['solrsort'] : 'ds_search_date';
    $this->sortdirection = isset($this->query_params['sortdirection']) ? $this->query_params['sortdirection'] : 'desc';
    $this->page = isset($this->query_params['page']) ? $this->query_params['page'] : '1';
    $this->rows = '10';
  }
 
  /**
   * Add a solr parameter
   * @see apachesolr_drupal_query()
   */
  public function addParam($key, $value) {
    $this->query->addParam($key, $value);
    return $this;
  }
 
  /**
   * Add a solr filter
   * @see apachesolr_drupal_query()
   */
  public function addFilter($key, $value) {
    $this->query->addFilter($key, $value);
    return $this;
  }
 
  /**
   * Add a solr sort
   * @see apachesolr_drupal_query()
   */
  public function setSolrsort($sort, $direction = 'desc'){
    $this->solrsort = $sort;
    $this->sortdirection = $direction;
  }
 
  /**
   * Set number of rows to return
   * @see apachesolr_drupal_query()
   */
  public function setRows($rows){
    $this->rows = $rows;
  }
 
  /**
   * Set some common parameters:
   * - sort field and direction
   * - start param
   * @see apachesolr_drupal_query()
   */
  protected function processRequest() {
    $this->addParam('sort', "$this->solrsort $this->sortdirection");
    $this->addParam('start', ($this->page -1) * $this->rows);
  }
 
  /**
   * Process the query and return the result
   * @see apachesolr_do_query()
   */
  public function doQuery() {
    $this->processRequest();
    return $this->query->search();
  }
 
}

Tags

Article Type

General