hook_apachesolr_node_exclude appears to have been dropped from BETA16 (and maybe before). What is the correct method for excluding nodes programatically now? Should this be included in the apachesolr.api.php file?

Comments

nick_vh’s picture

You should write a status callback and implement

function hook_apachesolr_entity_info_alter(&$entity_info) {

If you have a good example, please post it here so others can use this as a guidance

johnennew’s picture

Hi Nick_vh,

So I think I will actually replace the apachesolr default status callback with this method.

/**
 * Implements hook_apachesolr_entity_info_alter().
 */
function mymodule_apachesolr_entity_info_alter(&$entity_info) {
  $entity_info['node']['status callback'] = 'mymodule_apachesolr_index_node_status_callback';
}

/**
 * Status callback for ApacheSolr, for nodes. 
 */
function mymodule_apachesolr_index_node_status_callback($node, $type) {
  if ($node->type == 'news' && $node->some_custom_param == TRUE) {
    // Exclude this node which meets some custom criteria.
    return 0;
  }

  // Use the default apachesolr implementation otherwise.
  return apachesolr_index_node_status_callback($node, $type);
} 

I wonder if a hook in the apachesolr_index_node_status_callback function might be more elegant or a more general hook_apachesolr_entity_exclude() at a higher level?

nick_vh’s picture

Status: Active » Fixed

This code is 5 lines and you are looking for a more elegant solution? :-)

johnennew’s picture

Version: 7.x-1.0-beta16 » 7.x-1.x-dev
Status: Fixed » Needs review
StatusFileSize
new1.07 KB

OK, maybe not more elegant! But the previous method was much more straight forward for system integrators. This method requires a more detailed knowledge of the inner workings of the apachesolr module. This could be fixed with some more comments in the API file though, please find suggestion attached.

johnennew’s picture

Sorry, got the name of the hook wrong in the documentation. Here is an updated patch.

nick_vh’s picture

I'm all up for improvements in documentation ;-) Will commit something in this line to the api docs

sawtell’s picture

I found I had to include the apachesolr.index.inc file before calling apachesolr_index_node_status_callback() otherwise it caused fatal errors when publishing/unpublishing content.

  ...
  // added here
  module_load_include('inc', 'apachesolr', 'apachesolr.index');
  // Use the default apachesolr implementation otherwise.
  return apachesolr_index_node_status_callback($node, $type);
}
nick_vh’s picture

Status: Needs review » Fixed

Committed, thanks!

rbishop’s picture

thank you for this example, im having trouble getting the hook_apachesolr_entity_info_alter to fire. im on BETA16 and added #2 to my custom module

ive tried
drush solr-delete-index, drush solr-mark-all, drush solr-index
and tried to update my content and publish.

in my callback im just checking for nid == x to remove single nodes buy nid but dont see any changes to my results.

lazysoundsystem’s picture

I'm also having trouble with this with BETA16.

I can get the hook_apachesolr_entity_info_alter() to fire (twice) by clearing the cache, but not on indexing content - so my custom node_status_callback isn't getting picked up either.

I'll report back when I find out what's going on...

nick_vh’s picture

Status: Fixed » Postponed (maintainer needs more info)
sawtell’s picture

If you are marking all content to reindex, the process doesn't use the status callback.
The reindex callback is used which basically selects all bundles to be indexed straight from the node table.

See the default function in apachsolr.index.inc:

function apachesolr_index_node_solr_reindex($env_id) {
  $indexer_table = apachesolr_get_indexer_table('node');
  $transaction = db_transaction();
  try {
    db_delete($indexer_table)
      ->condition('entity_type', 'node')
      ->execute();
    $select = db_select('node', 'n');
    $select->addExpression("'node'", 'entity_type');
    $select->addField('n', 'nid', 'entity_id');
    $select->addField('n', 'type', 'bundle');
    $select->addField('n', 'status', 'status');
    $select->addExpression(REQUEST_TIME, 'changed');
    $select->condition('n.type', apachesolr_get_index_bundles($env_id, 'node'), 'IN');

    $insert = db_insert($indexer_table)
      ->fields(array('entity_id', 'bundle', 'status', 'entity_type', 'changed'))
      ->from($select)
      ->execute();
  }
  catch (Exception $e) {
    $transaction->rollback();
    //drupal_set_message($e->getMessage(), 'error');
    watchdog_exception('Apache Solr', $e);
    return FALSE;
  }

  return TRUE;
}

This means if you have something specific in your status callback such as excluding pages that are tagged with a certain term (e.g. no_index), the reindex function won't take that into account and will simply mark all content to index, regardless of whether or not that content is tagged with "no_index".

I had to alter the select query to index only the content I wanted indexed.

nick_vh’s picture

Status: Postponed (maintainer needs more info) » Needs work

That sounds like a bug indeed, we might need to loop over all content to make sure we use this exclude function.

nick_vh’s picture

Status: Needs work » Closed (duplicate)
duellj’s picture

Since this issue is linked to in apachesolr.api.php, it'd be helpful to note the correct way to add a status callback, since 'status callback' is now an array (to allow multiple status callbacks, which is great). Updated example from #2:

                  
/**
* Implements hook_apachesolr_entity_info_alter().
*/
function mymodule_apachesolr_entity_info_alter(&$entity_info) {
  $entity_info['node']['status callback'][] = 'mymodule_apachesolr_index_node_status_callback';
}

/**
* Status callback for ApacheSolr, for nodes.
*/
function mymodule_apachesolr_index_node_status_callback($entity_id, $type) {
  $node = node_load($entity_id, NULL, TRUE);
  if ($node->type == 'news' && $node->some_custom_param == TRUE) {
    // Exclude this node which meets some custom criteria.
    return 0;
  }

  return 1;
} 
nick_vh’s picture

Thanks!

osopolar’s picture

Version: 7.x-1.x-dev » 7.x-1.0-rc5
Status: Closed (duplicate) » Needs review

This issue is not a duplicate, because its about "What is the correct alternative approach to the hook_apachesolr_node_exclude".

And I am wondering, because hook_apachesolr_node_exclude() is still there. So I guess we don't need an alternative anymore. See also #904428: Document how to remove excluded nodes from index.

Setting this to "needs review" in case I am overlooking something.

nick_vh’s picture

Status: Needs review » Closed (works as designed)

There is no alternative :) The hook is back in the module