ซึ่งเป็นไปได้ด้วยตัวประมวลผล search_api แบบกำหนดเอง
ขั้นแรก ฉันสร้างคลาสนามธรรมเพื่อใช้เป็นฐานสำหรับฟังก์ชันที่ใช้ร่วมกัน เช่น. วิธีการจัดทำดัชนีข้อมูลเอนทิตีตามอำเภอใจด้วยเนื้อหา
เนมสเปซ Drupal\my_module\Plugin\search_api\processor;
ใช้ Drupal\Core\Entity\ContentEntityInterface
ใช้ Drupal\search_api\Datasource\DatasourceInterface
ใช้ Drupal\search_api\Item\ItemInterface
ใช้ Drupal\search_api\Processor\EntityProcessorProperty
ใช้ Drupal\search_api\Processor\ProcessorPluginBase
ใช้ Drupal\search_api\Utility\Utility;
/**
* คลาสปลั๊กอินพื้นฐานสำหรับการจัดทำดัชนีข้อมูลเอนทิตีที่เกี่ยวข้องโดยพลการ
*
* สิ่งนี้มีประโยชน์ในการจัดทำดัชนีคุณสมบัติของเอนทิตีที่อ้างอิงถึงเอนทิตีหรือ
* เอนทิตีที่เกี่ยวข้องในทางอื่นโดยพลการ
*
* @package Drupal\my_module\Plugin\search_api\processor
*/
คลาสนามธรรม RelatedEntityBase ขยาย ProcessorPluginBase {
/**
* {@inheritdoc}
*/
ฟังก์ชันสาธารณะ getPropertyDefinitions (DatasourceInterface $datasource = NULL) {
$plugin_definition = $this->getPluginDefinition();
คุณสมบัติ $ = [];
ถ้า (!$datasource || $datasource->getEntityTypeId() !== $this->getIndexedEntityTypeId()) {
ส่งคืนคุณสมบัติ $;
}
$definition = [
'label' => $plugin_definition['label'],
'คำอธิบาย' => $plugin_definition['คำอธิบาย'],
'type' => 'entity:' . $this->getRelatedEntityTypeId(),
'processor_id' => $this->getPluginId(),
'is_list' => จริง,
];
$property = ใหม่ EntityProcessorProperty($definition);
$property->setEntityTypeId($this->getRelatedEntityTypeId());
$properties[$this->getPluginId()] = $property;
ส่งคืนคุณสมบัติ $;
}
/**
* {@inheritdoc}
*/
ฟังก์ชันสาธารณะ addFieldValues (ItemInterface $item) {
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
$entity = $item->getOriginalObject()->getValue();
$to_extract = [];
foreach ($item->getFields() เป็น $field) {
$datasource = $field->getDatasource();
$property_path = $field->getPropertyPath();
[$direct, $nested] = ยูทิลิตี้::splitPropertyPath($property_path, FALSE);
ถ้า ($datasource && $datasource->getEntityTypeId() === $entity->getEntityTypeId() && $direct === $this->getPluginId()) {
$to_extract[$nested][] = $ฟิลด์;
}
}
foreach ($this->getRelatedEntities($entity) เป็น $relation) {
$this->getFieldsHelper()
->extractFields($relation->getTypedData(), $to_extract, $item->getLanguage());
}
}
/**
* รับอาร์เรย์ของเอนทิตีที่เกี่ยวข้อง
*
* สิ่งนี้ควรส่งคืนอาร์เรย์ของเอนทิตีที่โหลดเต็มซึ่งเกี่ยวข้องกับ
* $entity กำลังจัดทำดัชนี
*
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
* เอนทิตีที่กำลังจัดทำดัชนี
*
* @return อาร์เรย์
* อาร์เรย์ของเอนทิตีที่เกี่ยวข้องกับ $entity
*/
ฟังก์ชันป้องกันที่เป็นนามธรรม getRelatedEntities (ContentEntityInterface $entity): อาร์เรย์;
/**
* รับรหัสประเภทเอนทิตีของเอนทิตีที่กำลังจัดทำดัชนี
*
* นี่คือประเภทเอนทิตีของ $entity ที่ส่งผ่านไปยัง
* $this->getRelatedEntities()
*
* @return สตริง
* สตริง ID ประเภทเอนทิตี เช่น 'โหนด' 'สื่อ' หรือ 'taxonomy_term'
*/
ฟังก์ชั่นป้องกันนามธรรม getIndexedEntityTypeId (): สตริง;
/**
* รับรหัสประเภทเอนทิตีของเอนทิตีที่เกี่ยวข้อง
*
* นี่คือประเภทเอนทิตีของรายการที่ส่งคืน
* $this->getRelatedEntities()
*
* @return สตริง
* สตริง ID ประเภทเอนทิตี เช่น 'โหนด' 'สื่อ' หรือ 'taxonomy_term'
*/
ฟังก์ชันป้องกันที่เป็นนามธรรม getRelatedEntityTypeId(): สตริง;
}
ต่อไป ฉันสร้างคลาสปลั๊กอินที่ขยายคลาสนามธรรมสำหรับแต่ละกรณี (Collection's Authors, Article's Collections, Author's Collections) ตัวอย่างเช่น หากต้องการจัดทำดัชนีข้อมูลจากคอลเลกชันของบทความโดยเป็นส่วนหนึ่งของข้อมูลที่จัดทำดัชนีของบทความ:
เนมสเปซ Drupal\my_module\Plugin\search_api\processor;
ใช้ Drupal\Core\Entity\ContentEntityInterface
ใช้ Drupal\my_module\Plugin\search_api\processor\RelatedEntityBase
/**
* คุณสมบัติของดัชนีจากคอลเลกชันที่อ้างอิงถึงบทความ
*
* @SearchApiProcessor(
* id = "my_module_article_collections",
* label = @Translation("คอลเลกชันของบทความ"),
* คำอธิบาย = @Translation("คุณสมบัติของดัชนีจากคอลเลกชันที่อ้างอิงถึงบทความนี้"),
* ขั้นตอน = {
* "add_properties" = 0,
* },
* )
*/
คลาส ArticleCollections ขยาย RelatedEntityBase {
/**
* {@inheritdoc}
*/
ฟังก์ชันที่ได้รับการป้องกัน getRelatedEntities (ContentEntityInterface $entity): อาร์เรย์ {
ส่งคืน my_function_to_get_article_collections($entity)
}
/**
* {@inheritdoc}
*/
ฟังก์ชันที่ได้รับการป้องกัน getIndexedEntityTypeId (): สตริง {
ส่งคืน 'โหนด';
}
/**
* {@inheritdoc}
*/
ฟังก์ชันที่ได้รับการป้องกัน getRelatedEntityTypeId (): สตริง {
ส่งคืน 'โหนด';
}
}
สิ่งนี้ทำให้ฉันสามารถจัดทำดัชนีข้อมูลจากคอลเล็กชันโดยเป็นส่วนหนึ่งของข้อมูลของบทความได้ เช่น รหัสคอลเล็กชันของบทความ (เช่น รหัสคอลเล็กชันที่อ้างอิงถึงบทความ) ฉันสามารถจัดทำดัชนีฟิลด์ใดก็ได้จากคอลเลกชัน - โดยการเลือกฟิลด์ที่ฉันต้องการใน UI - เหมือนกับว่าบทความมีฟิลด์อ้างอิงเอนทิตีที่อ้างอิงคอลเล็กชัน (หมายเหตุ: ก่อนที่คุณจะจัดทำดัชนีฟิลด์ใดๆ ด้วยตัวประมวลผลแบบกำหนดเอง คุณต้องเปิดใช้งานตัวประมวลผลบนแท็บตัวประมวลผลสำหรับดัชนีของคุณก่อน)
ทั้งหมดนี้ใช้งานได้ดี อย่างไรก็ตาม ข้อมูลที่จัดทำดัชนีของฉันไม่ซิงค์กับความเป็นจริง ตัวอย่างเช่น หากฉันเพิ่มบทความใหม่ลงในคอลเล็กชัน ข้อมูลที่จัดทำดัชนีสำหรับบทความใหม่นั้นจะไม่ได้รับการอัปเดตด้วยข้อมูลสำหรับคอลเล็กชันใหม่ เช่น.บทความไม่ได้รับการจัดทำดัชนีใหม่หากมีการอัปเดตคอลเล็กชันที่อ้างถึง ฉันแก้ไขปัญหานี้ด้วย a hook_ENTITY_TYPE_update() การใช้งานที่ทำเครื่องหมายบทความที่เกี่ยวข้องเพื่อจัดทำดัชนีใหม่เมื่อบันทึกคอลเล็กชัน
ใช้ Drupal\node\NodeInterface;
/*
* ใช้ hook_ENTITY_TYPE_update()
*/
ฟังก์ชัน my_module_node_update (NodeInterface $node) {
ถ้า ($node->bundle() == 'คอลเลกชัน') {
$บทความ = [];
// รวบรวมบทความทั้งหมดที่คอลเลกชันนี้อ้างอิง
$articles = my_function_to_get_collection_articles($โหนด);
// รวบรวมบทความใด ๆ ที่ถูกอ้างอิงก่อนบันทึกนี้ด้วย
// ไม่อ้างอิงอีกต่อไป
$original_node = isset($node->original) ? $node->ต้นฉบับ : NULL;
ถ้า ($ original_node อินสแตนซ์ของ NodeInterface) {
$articles += my_function_to_get_collection_articles($original_node);
}
// ทำเครื่องหมายบทความที่จะจัดทำดัชนีใหม่
foreach ($ บทความเป็น $ บทความ) {
/** @var \Drupal\search_api\Plugin\search_api\datasource\ContentEntityTrackingManager $tracking_manager */
$search_api_tracking_manager = \Drupal::service('search_api.entity_datasource.tracking_manager');
$indexes = $search_api_tracking_manager->getIndexesForEntity($article);
ถ้า (!empty($indexes)) {
$item_ids = [];
foreach ($article->getTranslationLanguages() เป็น $langcode => $language) {
$item_ids[] = $article->id() ':' . $langcode;
}
foreach (ดัชนี $ เป็น $ ดัชนี) {
$index->trackItemsUpdated('entity:node', $item_ids);
}
}
}
}
}
หลังจากทั้งหมดนี้ ฉันสามารถจัดทำดัชนีข้อมูลจากเอนทิตีที่เกี่ยวข้องโดยพลการได้อย่างปลอดภัย