Điểm:2

Làm cách nào tôi có thể lập chỉ mục dữ liệu thực thể có liên quan tùy ý trong chỉ mục API Tìm kiếm giống như khi đó là tham chiếu thực thể?

lá cờ in

Tôi có một trang web với ba loại nội dung:

  • Bộ sưu tập (tham chiếu một đoạn tham chiếu Bài viết)
  • Bài viết (tham khảo Tác giả)
  • Tác giả

Tôi có hiển thị trang danh sách cho từng loại nội dung này. Các màn hình có các khía cạnh dựa trên các mối quan hệ trên.

  • Trang danh sách Bộ sưu tập có bộ lọc theo Tác giả. Mối quan hệ này không phải là mối quan hệ trực tiếp, mà là một chuỗi tham chiếu: Bộ sưu tập > Đoạn văn > Bài viết > Tác giả.
  • Trang liệt kê Bài viết có bộ lọc theo Bộ sưu tập. Mối quan hệ này cũng không phải là một tham chiếu trực tiếp, mà là một chuỗi các tham chiếu ngược lại: Bài báo < Đoạn văn < Bộ sưu tập.
  • Trang danh sách Tác giả cũng có bộ lọc theo Bộ sưu tập, đây cũng là một chuỗi tham chiếu ngược lại: Tác giả < Bài báo < Đoạn văn < Bộ sưu tập.

Theo như tôi biết, vì các khía cạnh này không dựa vào các mối quan hệ trực tiếp nên tôi không thể lập chỉ mục dữ liệu/tạo các khía cạnh với những gì search_api cung cấp ngay lập tức.

Tôi muốn lập chỉ mục dữ liệu thực thể có liên quan này với thực thể. Ví dụ: lập chỉ mục Bài viết của Bộ sưu tập như thể đó là tham chiếu thực thể trực tiếp. Tôi muốn lập chỉ mục Bộ sưu tập của Bài viết và Bộ sưu tập của Tác giả theo cùng một cách. Tôi muốn làm theo cách này vì nó sẽ chơi tốt với các khía cạnh và các thành phần khác một cách tự nhiên. Ngoài ra, điều này sẽ đặt hầu hết quá trình xử lý ở chế độ nền trong khi nội dung đang được lập chỉ mục thay vì khi màn hình đang được tạo hoặc truy vấn được thực thi

Làm thế nào điều này có thể đạt được?

Điểm:3
lá cờ in

Đ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 ý.

Đăng câu trả lời

Hầu hết mọi người không hiểu rằng việc đặt nhiều câu hỏi sẽ mở ra cơ hội học hỏi và cải thiện mối quan hệ giữa các cá nhân. Ví dụ, trong các nghiên cứu của Alison, mặc dù mọi người có thể nhớ chính xác có bao nhiêu câu hỏi đã được đặt ra trong các cuộc trò chuyện của họ, nhưng họ không trực giác nhận ra mối liên hệ giữa câu hỏi và sự yêu thích. Qua bốn nghiên cứu, trong đó những người tham gia tự tham gia vào các cuộc trò chuyện hoặc đọc bản ghi lại các cuộc trò chuyện của người khác, mọi người có xu hướng không nhận ra rằng việc đặt câu hỏi sẽ ảnh hưởng—hoặc đã ảnh hưởng—mức độ thân thiện giữa những người đối thoại.