Max Rosenbaum
Software developer
Monday, 29 November 2021
Update search index on entity update in drupal 8
By default, Drupal's search index queues entities for index on save. When cron executes the search index does a batch process on the nodes that were queued for update.
A project I was working on had a requirement to update the solr search index immediately when someone saved a node or when a node was imported by a batch process. My solution to the problem was to use the hook event dispatcher module to get an event to fire for the entities updating, the process the index update in the event handler.
Indexing the node into the search index is a simple process of calling indexSpecificItems
with the entities
getTypedData
result. This wasn't
super clear from the documentation, and hopefully it helps someone with the same problem.
Here is an example;
public function onEntityUpdate(EntityEvent $event){
$entity = $event->getEntity();
// We were using the search index provided by acquia
$index = Index::load('acquia_search_index');
// Check the status was published so we don't accidentally index things the public is not supposed to see.
if ((int)$entity->__get('status')->getString() === 1) {
// This is the indexing process here, this could be quite a heavy or slow call depending on your search setup
$index->indexSpecificItems([$entity->getTypedData()]);
}
// Beware that this is just appending the langauage code on the end, if you're on a
// multi language site you'll need to extend this to get the active language codes of the
// current node.
//
// The reason we delete here, is that if the status was updated to draft/unpublished in drupal, we need to
// remove the entity from the search index right away, as to not show to the public.
$index->trackItemsDeleted('entity:node', array("{$entity->id()}:en"));
}
Given the above, you can also do any actions you need on the search index with any of the other provided event
listeners in the hook_event_dispatcher
module. I would consider using events over hooks wherever possible as a best
practice in drupal 9. Use it where you can!