Apache Solr Spielerei

If you haven't heard of Apache Solr and the integration with Drupal, than you're probably still struggling with the default search shipped with Drupal core. Pity you. Now, this won't be an introduction on the excellent search engine, no, this is a tale about the combination between Apache Solr, node caching and Node displays. Take a look at following snippet:

<?php
/**
* Creme de la creme:
* Put the full node object in the index, so no node_loads are needed for results.
*/
function nd_search_apachesolr_update_index(&$document, $node) {
 
$node->body = $node->content['body']['#value'];
  unset(
$node->content);
 
$document->tm_node = serialize($node);
}
?>

This code lives in nd_search, a small contrib which you can download from the Node Displays Contributions project. This code indexes the complete node object into the Apache Solr engine which you can you use later on either in custom code or on the search results page. Drupal core gives you the freedom to define a custom search function to render the results instead of the default page, which is - IMHO - pretty hard to customize. ND search implements hook_search_page and in combination with the power of ND, we have full control how to render a node per content type, and this without getting any extra data from the database. The code underneath explains it all.

<?php
/**
* Get the serialized version from the node, and unserialize it.
* @param $doc The apache solr document to be converted.
*
* @return Node version from the document.
*/
function _solr_document_to_node($doc) {
 
$node_serialized = $doc['node']->getField('tm_node');
 
$node = unserialize($node_serialized['value']);
  return
$node;
}

/**
* Implementation of hook_search_page().
*/
function apachesolr_search_search_page($results) {
$output = '';

  foreach (

$results as $key => $result) {
   
$node = _solr_document_to_node($result);
   
$node->build_mode = NODE_BUILD_SEARCH_RESULT;
   
$output .= node_view($node);
  }

 

$output .= theme('pager', NULL, 10, 0);

  return

$output;
}
?>

Pretty cool, right? The module also indexes all CCK fiels for you which you can use in custom code if you want to fire custom queries on one of those fields. Following snippet comes from a block where we want to search on a CCK field called 'name'. The result we get back uses the same function to unserialize the node object and after that we call node_view which is altered through the ND module with a custom build mode. Score again!

<?php
  $filter
= 'ss_cck_field_name:swentel';
 
$search_results = apachesolr_search_execute($filter, '', '');
 
$output = '';
  foreach (
$search_results as $key => $result) {
   
$nid = $result['node']->getField('nid');
    if (
$nid['value'] == arg(1)) { // Don't list the same node we're looking at right now.
     
continue;
    }
   
$node = _solr_document_to_node($result);
   
$node->build_mode = 'nd_blocks';
   
$output .= node_view($node, FALSE, FALSE);
  }
  return
$output;
?>

With this power, imagine a search results page with 2 or 3 blocks which doesn't fire any extra queries at the database for extra data. Our ultimate - and probably improbably - dream is to cache all data in apache solr so we don't need to access MySQL anymore. Of course, that's bullocks, but with the project we're currently building (more than 300K nodes to start with) we're pretty sure we'll be able to deliver a nice search experience for our end users.

Note: I'm pretty biased when it comes to the ND project since I'm one of the co-developers , but hey, we're so excited about it and we're planning a lot of new features pretty soon, but more news on that later!

Comments

You are here