11

I'm working on Sear API. My entity has many items and data change by action of the user. I don't want to reindex all items of data. So I want to reindex an entity after user does the action. I found the topic but just for Drupal 7. So with search API for Drupal 8, how to I can implement force search API to reindex an entity? The way or snippet code I can use? Please help!

e.g. I have search index with some basic field like this:

enter image description here

I want to update the number of comment value after use add a new comment. Default search api doesn't not support that. And I don't want to wait for a cron to update value. Imagine one field very important not like the number of comment. That field needs to update immediately.

4 Answers 4

15

You can dive deep into the code of search_api to find solution for issue. See function search_api_entity_update() and search_api_search_api_index_update(). In case reindex number of comment, you can try this code:

// Example reindex after has new comment at node article id 1
$entity = Node::load(1);
$indexes = ContentEntity::getIndexesForEntity($entity);

foreach ($indexes as $index) {
    // Becarefull with indexes. Just for this case.
    // $datasource_id: entity:node (entity type)
    // $updated_item_ids: 1:en (node ID and Language)
    $index->trackItemsUpdated('entity:node', ['1:en']);
}

You can debug in search_api.module to more info.

3

Same as D7, you do not need to implicitly mark the entity to be reindexed by Search API. It already does the work for you.

In the module file, there is an implementation of hook_entity_update(), which takes care of reindexing the items immediately. Not required to wait for the cron run.

I have created a site on simplytest https://du6hi.ply.st (admin/admin) to confirm.

6
  • thanks for help. But I want to update immediately. Don't wait cron to reindex.
    – Jonh
    Jan 2, 2018 at 17:18
  • @Jonh I misread the implementation in the code. You do not need to wait for the cron run. The items are reindexed automatically. Edited the answer to reflect it.
    – AjitS
    Jan 3, 2018 at 6:31
  • Try with du6hi.ply.st/seach and add new comment at node/10.
    – Jonh
    Jan 3, 2018 at 6:46
  • The search index would not be affected by comments. That is because comment entity is not selected to be indexed by the datasource. du6hi.ply.st/admin/config/search/search-api/index/default_index/… @Jonh
    – AjitS
    Jan 3, 2018 at 6:48
  • 1
    There are various use-cases where you may want to re-index a page or entity, such as a page using paragraphs with a block which is an embedded view of other entities; Updating the other entities will not automatically re-trigger indexing of the page on which the view is displayed.
    – Duncanmoo
    Feb 15, 2018 at 7:55
3

I've found that the solution by MrD does not index immediately. I assume it adds the item to a queue which will process on cron.

If you need the item to be indexed immediately try this:

$node_id = 123;
$index = Index::load('my_index');
$language = \Drupal::languageManager()->getCurrentLanguage()->getId();
$item_id = 'entity:node/' . $node_id . ':' . $language;
$items = [];
$items[$item_id] = $index->loadItem($item_id);
$index->indexSpecificItems($items);

You'll have to modify if you're indexing something other than a node.

1

As remarked by @Duncanmoo (D7), there are various use-cases where you may want to re-index a page or entity yourself in custom code.

In my case the relevant node entity updates were implemented like this :

$node = node_load($nid);
$node->field_search_rank[LANGUAGE_NONE][0]['value'] = $movie->order;
field_attach_presave('node', $node);
field_attach_update('node', $node);
entity_get_controller('node')->resetCache([$node->nid]);

Yet, search_api_entity_update() was not triggered to have the updated field re-indexed to Solr, since the hook doesn't listen to field_attach_update()

Instead, I applied this suggested additional custom code to complete the re-indexation on each item.

$node = node_load($nid);
$node->field_search_rank[LANGUAGE_NONE][0]['value'] = $movie->order;
field_attach_presave('node', $node);
field_attach_update('node', $node);
entity_get_controller('node')->resetCache([$node->nid]);
// Re-index the node updates : 
search_api_track_item_change('node', array($node->nid));
$combined_id = 'node/' . $node->nid;
search_api_track_item_change('multiple', array($combined_id));

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.