Problem/Motivation
On 8.x-7.x there was no Event for altering the settings when creating the index. One could use PrepareIndexEvent
(https://git.drupalcode.org/project/elasticsearch_connector/-/blob/8.x-7....) to alter Elasticsearch index settings based on Search API index configurations.
eg. set stemmer based on indexed content.
<?php
namespace Drupal\MY_MODULE\EventSubscriber;
use Drupal\Component\EventDispatcher\Event;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\elasticsearch_connector\ElasticSearch\Parameters\Factory\IndexFactory;
use Drupal\search_api\IndexInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Class EntityTypeSubscriber.
*
* @package Drupal\MY_MODULE\EventSubscriber
*/
class PrepareIndexSubscriber implements EventSubscriberInterface {
/**
* Entity type manager.
*
* @var \Drupal\Core\Entity\Entity
*/
private $entityTypeManager;
/**
* Constructs a new DefaultSubscriber object.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* Entity type manager.
*/
public function __construct(EntityTypeManagerInterface $entityTypeManager) {
$this->entityTypeManager = $entityTypeManager;
}
/**
* {@inheritdoc}
*
* @return array
* The event names to listen for, and the methods that should be executed.
*/
public static function getSubscribedEvents() {
return [
'elasticsearch_connector.prepare_index' => 'prepareIndex',
];
}
/**
* Called on elasticsearch_connector.prepare_index event.
*/
public function prepareIndex(Event $event) {
$indexConfig = $event->getIndexConfig();
$index = $this->loadIndexFromIndexName($event->getIndexName());
$config = $this->getDatasourceConfig($index);
$stemmer_language = 'english';
if (!empty($config) && isset($config['languages']['selected'])) {
$langcode = $config['languages']['selected'][0];
if ($langcode === 'fi') {
$stemmer_language = 'finnish';
}
}
$filter_name = $stemmer_language . '_stop';
$filter_language = '_' . $stemmer_language . '_';
$indexConfig["body"]["settings"]["index"] = [
"analysis" => [
"analyzer" => [
"tags_analyzer" => [
"type" => "custom",
"filter" => [
"lowercase",
"stop",
"filter_stemmer",
$filter_name,
],
"tokenizer" => "standard",
],
],
"filter" => [
"filter_stemmer" => [
"type" => "stemmer",
"language" => $stemmer_language,
],
$filter_name => [
"type" => "stop",
"stopwords" => $filter_language,
],
],
],
];
$event->setIndexConfig($indexConfig);
}
/**
* Loads the index entity associated with this event.
*
* @param string $index_name
* The long index name as a string.
*
* @return \Drupal\Core\Entity\EntityInterface|null
* The loaded index or NULL.
*/
private function loadIndexFromIndexName($index_name) {
$index_storage = $this->entityTypeManager->getStorage('search_api_index');
/** @var \Drupal\search_api\Entity\Index[] $search_api_indexes */
$search_api_indexes = $index_storage->loadMultiple();
foreach ($search_api_indexes as $search_api_index) {
$elasticsearch_connector_index_name = IndexFactory::getIndexName($search_api_index);
if ($index_name == $elasticsearch_connector_index_name) {
return $search_api_index;
}
}
return NULL;
}
/**
* Returns the datasource configuration for the given index.
*
* @param \Drupal\search_api\IndexInterface $index
* The Search API index entity.
*
* @return array
* An array representing the datasource configuration.
*
* @throws \Drupal\search_api\SearchApiException
*/
protected function getDatasourceConfig(IndexInterface $index) {
$config = [];
if ($index->isValidDatasource('entity:node')) {
$config = $index->getDatasource('entity:node')->getConfiguration();
}
return $config;
}
}
Proposed resolution
Add Drupal\search_api\IndexInterface $index
to AlterSettingsEvent constructor argument.
Remaining tasks
User interface changes
None.
API changes
The \Drupal\elasticsearch_connector\Event\AlterSettingsEvent
now stores a reference to the Elasticsearch index (i.e.: an instance of \Drupal\search_api\IndexInterface
), which you can retrieve with \Drupal\elasticsearch_connector\Event\AlterSettingsEvent->getIndex()
.
Data model changes
None.