0

I have a content type in a D6 site that allows the creator of a node to mark the node as "withdrawn" -- he can still see it, but attempts by others to see it are caught and redirected somewhere else, like their user page. When this node gets withdrawn, I'd like to remove it from the local search index (standard Drupal search) as well.

My somewhat brutish way of doing this is:

    db_query("delete from {search_dataset} where sid = %d", $node->nid);
    db_query("delete from {search_index} where sid = %d", $node->nid);

which seems to work -- the node stops showing up in search results. But I'm worried about {search_total} -- there are entries there that correspond to the words in the node's content. I can't just remove all the node's terms from {search_total}, of course; is this worth worrying about? Or am I seriously screwing up the search index by doing this in the first place? Thanks!

1 Answer 1

1

Looking at the code executed from node_delete_multiple() (which is then the function used by node_delete()), I see that the function called is search_reindex().

    // Remove this node from the search index if needed.
    // This code is implemented in node module rather than in search module,
    // because node module is implementing search module's API, not the other
    // way around.
    if (module_exists('search')) {
      search_reindex($nid, 'node');
    }

The code executed from that function to delete rows from the search tables is the following one.

db_delete('search_dataset')
  ->condition('sid', $sid)
  ->condition('type', $module)
  ->execute();

db_delete('search_index')
  ->condition('sid', $sid)
  ->condition('type', $module)
  ->execute();

// Don't remove links if re-indexing.
if (!$reindex) {
  db_delete('search_node_links')
    ->condition('sid', $sid)
    ->condition('type', $module)
    ->execute();
}

I suggest using search_reindex(), but to reply to your question, it doesn't seem that updating the "search_total" table is necessary, at this point; Drupal doesn't do it when a node is deleted. That table is updated from search_update_totals(), which is called from search_cron(). See the comment given for the following code, executed from search_update_totals().

  // Find words that were deleted from search_index, but are still in
  // search_total. We use a LEFT JOIN between the two tables and keep only the
  // rows which fail to join.
  $result = db_query("SELECT t.word AS realword, i.word FROM {search_total} t LEFT JOIN {search_index} i ON t.word = i.word WHERE i.word IS NULL", array(), array('target' => 'slave'));
  $or = db_or();
  foreach ($result as $word) {
    $or->condition('word', $word->realword);
  }
  if (count($or) > 0) {
    db_delete('search_total')
      ->condition($or)
      ->execute();
  }

In Drupal 6, the equivalent of search_reindex() is search_wipe(), which is called from node_delete(). The function contains the following code to delete the tables' content.

db_query("DELETE FROM {search_dataset} WHERE sid = %d AND type = '%s'", $sid, $type);
db_query("DELETE FROM {search_index} WHERE sid = %d AND type = '%s'", $sid, $type);
// Don't remove links if re-indexing.
if (!$reindex) {
  db_query("DELETE FROM {search_node_links} WHERE sid = %d AND type = '%s'", $sid, $type);
}

Also in this case, I suggest using search_wipe().

3
  • Good suggestion (= "duh, I should have thought of that"); thanks! I'm working in Drupal 6, but D7's search_reindex() appears to just be a conversion of D6's search_rewrite(). I think I'd be safe doing what I'm doing, but using the "real" function is a better idea.
    – Jim Miller
    May 27, 2012 at 1:26
  • The Drupal 6 equivalent is search_wipe(); I have updated my answer.
    – apaderno
    May 27, 2012 at 2:46
  • Hmm -- there's another aspect to this matter. The approach outlined here does seem to remove the node from the index. However, since the node still exists, it'll be re-indexed the next time (more or less) that cron runs. From the looks of node_update_index() in D6, and some experimentation, it looks like I'll be OK if I leave the entry in {search_dataset} and make sure that the node's REINDEX field is 0. As long as I don't reset the search index (thus setting all nodes' reindex to a non-zero value), anyway... Does this make sense?
    – Jim Miller
    May 27, 2012 at 15:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.