Score:2

ฉันจะจัดทำดัชนีข้อมูลเอนทิตีที่เกี่ยวข้องโดยพลการในดัชนี Search API ให้เหมือนกับข้อมูลอ้างอิงเอนทิตีได้อย่างไร

ธง in

ฉันมีไซต์ที่มีเนื้อหาสามประเภท:

  • การรวบรวม (อ้างอิงย่อหน้าที่อ้างอิงบทความ)
  • บทความ (อ้างอิงผู้เขียน)
  • ผู้เขียน

ฉันมีหน้ารายชื่อที่แสดงสำหรับเนื้อหาแต่ละประเภทเหล่านี้ การแสดงผลมีแง่มุมตามความสัมพันธ์ข้างต้น

  • หน้ารายการคอลเลกชันมีตัวกรองตามผู้แต่ง ความสัมพันธ์นี้ไม่ใช่ความสัมพันธ์โดยตรง แต่เป็นห่วงโซ่ของการอ้างอิง: คอลเลกชัน > ย่อหน้า > บทความ > ผู้แต่ง
  • หน้ารายชื่อบทความมีตัวกรองตามคอลเลกชัน ความสัมพันธ์นี้ไม่ใช่การอ้างอิงโดยตรง แต่เป็นห่วงโซ่ของการอ้างอิงย้อนกลับ: บทความ < ย่อหน้า < คอลเลกชัน
  • หน้ารายชื่อผู้แต่งยังมีตัวกรองตามคอลเล็กชันซึ่งเป็นห่วงโซ่ของการอ้างอิงย้อนกลับ: ผู้แต่ง < บทความ < ย่อหน้า < คอลเล็กชัน

เท่าที่ฉันทราบ เนื่องจาก facet เหล่านี้ไม่ได้อาศัยความสัมพันธ์โดยตรง ฉันจึงไม่สามารถจัดทำดัชนีข้อมูล / สร้าง facets จากสิ่งที่ search_api มอบให้ได้ทันที

ฉันต้องการจัดทำดัชนีข้อมูลเอนทิตีที่เกี่ยวข้องนี้กับเอนทิตี ตัวอย่างเช่น จัดทำดัชนีบทความของคอลเลกชั่นราวกับว่ามันเป็นการอ้างอิงเอนทิตีโดยตรง ฉันต้องการจัดทำดัชนีคอลเลกชันของบทความและคอลเลกชันของผู้แต่งด้วยวิธีเดียวกัน ฉันต้องการทำเช่นนี้เนื่องจากควรเล่นได้ดีกับ facets และส่วนประกอบอื่น ๆ นอกจากนี้ การดำเนินการนี้จะทำให้การประมวลผลส่วนใหญ่อยู่เบื้องหลังในขณะที่เนื้อหากำลังถูกจัดทำดัชนี แทนที่จะเป็นขณะที่กำลังสร้างจอแสดงผลหรือคิวรีถูกดำเนินการ

วิธีนี้สามารถทำได้?

Score:3
ธง in

ซึ่งเป็นไปได้ด้วยตัวประมวลผล 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);
        }
      }
    }
  }
}

หลังจากทั้งหมดนี้ ฉันสามารถจัดทำดัชนีข้อมูลจากเอนทิตีที่เกี่ยวข้องโดยพลการได้อย่างปลอดภัย

โพสต์คำตอบ

คนส่วนใหญ่ไม่เข้าใจว่าการถามคำถามมากมายจะปลดล็อกการเรียนรู้และปรับปรุงความสัมพันธ์ระหว่างบุคคล ตัวอย่างเช่น ในการศึกษาของ Alison แม้ว่าผู้คนจะจำได้อย่างแม่นยำว่ามีคำถามกี่ข้อที่ถูกถามในการสนทนา แต่พวกเขาไม่เข้าใจความเชื่อมโยงระหว่างคำถามและความชอบ จากการศึกษาทั้ง 4 เรื่องที่ผู้เข้าร่วมมีส่วนร่วมในการสนทนาด้วยตนเองหรืออ่านบันทึกการสนทนาของผู้อื่น ผู้คนมักไม่ตระหนักว่าการถามคำถามจะมีอิทธิพลหรือมีอิทธิพลต่อระดับมิตรภาพระหว่างผู้สนทนา