Điều này có thể thực hiện được với bộ xử lý search_api tùy chỉnh.
Đầu tiên, tôi đã tạo một lớp trừu tượng để sử dụng làm cơ sở cho chức năng được chia sẻ. I E. một phương pháp để lập chỉ mục dữ liệu thực thể tùy ý với một phần nội dung.
không gian tên Drupal\my_module\Plugin\search_api\bộ xử lý;
sử dụng Drupal\Core\Entity\ContentEntityInterface;
sử dụng Drupal\search_api\Datasource\DatasourceInterface;
sử dụng Drupal\search_api\Item\ItemInterface;
sử dụng Drupal\search_api\Processor\EntityProcessorProperty;
sử dụng Drupal\search_api\Processor\ProcessorPluginBase;
sử dụng Drupal\search_api\Utility\Utility;
/**
* Lớp plugin cơ sở để lập chỉ mục dữ liệu thực thể liên quan tùy ý.
*
* Điều này có thể hữu ích để lập chỉ mục các thuộc tính của các thực thể tham chiếu đến một thực thể hoặc
* các thực thể liên quan theo một số cách tùy ý khác.
*
* @package Drupal\my_module\Plugin\search_api\bộ xử lý
*/
lớp trừu tượng RelatedEntityBase mở rộng ProcessorPluginBase {
/**
* {@inheritdoc}
*/
hàm công khai getPropertyDefinitions(DatasourceInterface $datasource = NULL) {
$plugin_definition = $this->getPluginDefinition();
thuộc tính $ = [];
if (!$datasource || $datasource->getEntityTypeId() !== $this->getIndexedEntityTypeId()) {
trả lại thuộc tính $;
}
định nghĩa $ = [
'nhãn' => $plugin_definition['nhãn'],
'mô tả' => $plugin_definition['mô tả'],
'loại' => 'thực thể:' . $this->getRelatedEntityTypeId(),
'processor_id' => $this->getPluginId(),
'is_list' => ĐÚNG,
];
$property = new EntityProcessorProperty($definition);
$property->setEntityTypeId($this->getRelatedEntityTypeId());
$properties[$this->getPluginId()] = $property;
trả lại thuộc tính $;
}
/**
* {@inheritdoc}
*/
hàm công cộng addFieldValues(ItemInterface $item) {
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
$entity = $item->getOriginalObject()->getValue();
$to_extract = [];
foreach ($item->getFields() as $field) {
$datasource = $field->getDatasource();
$property_path = $field->getPropertyPath();
[$direct, $nested] = Tiện ích::splitPropertyPath($property_path, FALSE);
if ($datasource && $datasource->getEntityTypeId() === $entity->getEntityTypeId() && $direct === $this->getPluginId()) {
$to_extract[$nested][] = $field;
}
}
foreach ($this->getRelatedEntities($entity) as $relation) {
$this->getFieldsHelper()
->extractFields($relation->getTypedData(), $to_extract, $item->getLanguage());
}
}
/**
* Nhận một mảng các thực thể liên quan.
*
* Điều này sẽ trả về một mảng các thực thể được tải đầy đủ liên quan đến
* Thực thể $ đang được lập chỉ mục.
*
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
* Thực thể được lập chỉ mục.
*
* @return mảng
* Một mảng các thực thể liên quan đến $entity.
*/
hàm được bảo vệ trừu tượng getRelatedEntities(ContentEntityInterface $entity): mảng;
/**
* Lấy id loại thực thể của thực thể được lập chỉ mục.
*
* Đây là loại thực thể của $entity được chuyển đến
* $this->getRelatedEntities().
*
* chuỗi @return
* Chuỗi id loại thực thể, ví dụ: 'nút', 'phương tiện' hoặc 'taxonomy_term'.
*/
hàm được bảo vệ trừu tượng getIndexedEntityTypeId(): string;
/**
* Lấy id loại thực thể của các thực thể liên quan.
*
* Đây là loại thực thể của các mục được trả về từ
* $this->getRelatedEntities().
*
* chuỗi @return
* Chuỗi id loại thực thể, ví dụ: 'nút', 'phương tiện' hoặc 'taxonomy_term'.
*/
hàm được bảo vệ trừu tượng getRelatedEntityTypeId(): string;
}
Tiếp theo, tôi đã tạo các lớp plugin mở rộng lớp trừu tượng của mình cho từng trường hợp (Tác giả của Bộ sưu tập, Bộ sưu tập của Bài báo, Bộ sưu tập của Tác giả). Ví dụ: để lập chỉ mục dữ liệu từ Bộ sưu tập của Bài viết như một phần của dữ liệu được lập chỉ mục của Bài viết:
không gian tên Drupal\my_module\Plugin\search_api\bộ xử lý;
sử dụng Drupal\Core\Entity\ContentEntityInterface;
sử dụng Drupal\my_module\Plugin\search_api\bộ xử lý\RelatedEntityBase;
/**
* Thuộc tính chỉ mục từ Bộ sưu tập tham chiếu đến một Bài viết.
*
* @SearchApiProcessor(
* id = "my_module_article_collections",
* nhãn = @Translation("Bộ sưu tập của bài báo"),
* description = @Translation("Thuộc tính chỉ mục từ Bộ sưu tập tham khảo Bài viết này."),
* giai đoạn = {
* "thêm_thuộc tính" = 0,
* },
* )
*/
class ArticleCollections extends RelatedEntityBase {
/**
* {@inheritdoc}
*/
hàm được bảo vệ getRelatedEntities(ContentEntityInterface $entity): mảng {
trả về my_function_to_get_article_collections($entity)
}
/**
* {@inheritdoc}
*/
chức năng được bảo vệ getIndexedEntityTypeId (): chuỗi {
trả lại 'nút';
}
/**
* {@inheritdoc}
*/
chức năng được bảo vệ getRelatedEntityTypeId (): chuỗi {
trả lại 'nút';
}
}
Điều này cho phép tôi lập chỉ mục dữ liệu từ Bộ sưu tập như một phần dữ liệu của Bài viết, ví dụ: Id Bộ sưu tập của Bài viết (tức là Id của Bộ sưu tập tham chiếu Bài viết). Tôi có thể lập chỉ mục bất kỳ trường nào từ Bộ sưu tập - bằng cách chọn trường tôi muốn trong Giao diện người dùng - giống như khi Bài viết có trường tham chiếu thực thể tham chiếu đến Bộ sưu tập. (Lưu ý: trước khi bạn có thể lập chỉ mục bất kỳ trường nào bằng bộ xử lý tùy chỉnh, trước tiên bạn phải bật nó trên tab Bộ xử lý cho chỉ mục của mình.)
Tất cả điều này đều hoạt động tốt, tuy nhiên, dữ liệu được lập chỉ mục của tôi không được đồng bộ hóa với thực tế. Ví dụ: nếu tôi đã thêm Bài viết mới vào Bộ sưu tập, dữ liệu được lập chỉ mục cho Bài viết mới đó sẽ không được cập nhật với thông tin cho Bộ sưu tập mới. I E.Bài báo không được lập chỉ mục lại nếu Bộ sưu tập tham chiếu đến nó được cập nhật. tôi đã giải quyết điều này với một hook_ENTITY_TYPE_update() triển khai đánh dấu các Bài viết phụ thuộc sẽ được lập chỉ mục lại khi Bộ sưu tập được lưu.
sử dụng Drupal\node\NodeInterface;
/*
* Triển khai hook_ENTITY_TYPE_update().
*/
function my_module_node_update(NodeInterface $node) {
if ($node->bundle() == 'bộ sưu tập') {
bài viết $ = [];
// Tập hợp tất cả các Bài viết mà Bộ sưu tập này tham chiếu.
$articles = my_function_to_get_collection_articles($node);
// Cũng thu thập bất kỳ Bài viết nào đã được tham chiếu trước khi lưu này, nhưng
// không còn được tham chiếu nữa.
$ original_node = isset($node-> original) ? $node->gốc : NULL;
if ($ original_node instanceof NodeInterface) {
$articles += my_function_to_get_collection_articles($ original_node);
}
// Đánh dấu các bài viết sẽ được lập chỉ mục lại.
foreach ($articles as $article) {
/** @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);
if (!empty($indexes)) {
$item_ids = [];
foreach ($article->getTranslationLanguages() as $langcode => $language) {
$item_ids[] = $article->id() . ':' . mã ngôn ngữ $;
}
foreach ($index là $index) {
$index->trackItemsUpdated('entity:node', $item_ids);
}
}
}
}
}
Sau tất cả những điều này, tôi có thể lập chỉ mục dữ liệu một cách an toàn từ các thực thể có liên quan tùy ý.