Filtering Apache Solr search results based on dynamic fields

You may often have content in Drupal that should not appear for certain user roles. There are many ways to accomplish this in the CMS, but restricting them from search results is often overlooked. If you are using Apache Solr for your search engine, the apachesolr_nodeaccess module integrates with Drupal’s node access system to restrict results. However, what if your access rules are more fine-grained than just content types?

What if users are restricted from viewing certain content based on taxonomy terms or vocabularies?

Brad Blake
#Development | Posted

You may often have content in Drupal that should not appear for certain user roles. There are many ways to accomplish this in the CMS, but restricting them from search results is often overlooked. If you are using Apache Solr for your search engine, the apachesolr_nodeaccess module integrates with Drupal’s node access system to restrict results. However, what if your access rules are more fine-grained than just content types?

What if users are restricted from viewing certain content based on taxonomy terms or vocabularies? ( something accomplished in the CMS with modules such as Taxonomy Access Control Lite )

You could return all results and use logic in your template to determine if a result should be shown to a user, but it’s much more efficient to use the apachesolr module’s hooks to determine what search results are returned.

We’ll focus on two hooks provided by the apachesolr module: hook_apachesolr_update_index and hook_apachesolr_modify_query.

hook_apachesolr_update_index is invoked whenever a node is being indexed by Apache Solr. You can use this hook to modify attributes of the node or create your own custom fields before the node gets indexed. The following function adds two custom fields.

  1. function mymodule_apachesolr_update_index(&$document, $node) {
  2. .. code to determine values ..
  3.  
  4. $document->addField('is_example_1', $example1_value);
  5. $document->addField('is_example_2', $example2_value);
  6. }

The ‘is_’ prefix on the field name is important. Solr has a list of pre-defined prefixes located in the schema.xml file in your apachesolr module directory. Look for the section marked “Dynamic field definitions”, which lists all possible field name prefixes and their associated data types. If you create a custom field that does not include one of these prefixes, your field will not be added to the index.

To make sure your field is being included, look at the status page ( /admin/reports/apachesolr ) to see all current fields in the index.

hook_apachesolr_modify_query is invoked before the search query is sent to Solr. Here we can filter out nodes based on the fields we created. In the following example, we add filters to the query based on user permissions.

  1. function mymodule_apachesolr_modify_query(&$query, &$params, $caller) {
  2. if (!user_access("access example1 content")) {
  3. $query->add_filter("is_example_1", 1, TRUE);
  4. }
  5. if (!user_access("access example2 content")) {
  6. $query->add_filter("is_example_2", 1, TRUE);
  7. }
  8. }

The first parameter to the add_filter function is the field name, the second is the value to search on, and the third is a boolean value. If this value is true, then matching items are removed from the result set. You can add filters on any of the fields that are in the index such as node type or status, not just ones that you have created.

Either of these hooks can be used on their own, but together they allow for very powerful control over the search results presented to your users.

Brad Blake