Score:0

ดำเนินการ entityQuery ด้วยเงื่อนไขหลายฟิลด์ในฟิลด์ที่อ้างอิง

ธง um

ฉันมีประเภทโหนดบทความที่มีฟิลด์อ้างอิงถึงบทความที่เกี่ยวข้อง หากบทความมีแหล่งอ้างอิงน้อยกว่า 4 ช่อง ฉันต้องค้นหาบทความอื่นที่

  • ไม่ใช่โหนดปัจจุบัน
  • ได้รับการปรับปรุงน้อยกว่า 2 ปีที่ผ่านมา
  • ทำเครื่องหมายที่ช่อง 'รายการโปรด'
  • แบ่งปันรหัสวัฒนธรรมอย่างน้อยหนึ่งรายการ (การอ้างอิงอนุกรมวิธาน) และรหัสธีมอย่างน้อยหนึ่งรายการ (การอ้างอิงอนุกรมวิธาน)

และฉันก็สงสัยจริง ๆ ว่าจะทำความต้องการสุดท้ายนั้นอย่างไร... ขึ้นอยู่กับ ดำเนินการค้นหาด้วยเงื่อนไขฟิลด์เอนทิตีที่มีหลายค่าฉันเขียนรหัสต่อไปนี้:

<?php

เนมสเปซ Drupal\my_module\Preprocess;

ใช้ Drupal\Core\DependencyInjection\ContainerInjectionInterface;
ใช้ Drupal\Core\Entity\EntityTypeManagerInterface;
ใช้ Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * บทความประเภทโหนดการประมวลผลล่วงหน้า
 */
คลาส MyArticle ใช้ ContainerInjectionInterface {

  const MAX_RELATED_ARTICLES = 4;

  /**
   * การจัดเก็บระยะอนุกรมวิธาน
   *
   * @var \Drupal\node\NodeStorage
   */
  ป้องกัน $nodeStorage;

  /**
   * ตัวสร้างคลาส
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   * ผู้จัดการประเภทเอนทิตี
   */
  ฟังก์ชั่นสาธารณะ __construct (EntityTypeManagerInterface $entity_type_manager) {
    $this->nodeStorage = $entity_type_manager->getStorage('โหนด');
  }

  /**
   * {@inheritdoc}
   */
  สร้างฟังก์ชันคงที่สาธารณะ (ContainerInterface $container) {
    ส่งคืนค่าคงที่ใหม่ (
      $container->get('entity_type.manager')
    );
  }

  /**
   * บทความประเภทโหนดการประมวลผลล่วงหน้า
   *
   * @param อาร์เรย์ $ตัวแปร
   * อาร์เรย์ของตัวแปรที่ใช้ในการเรนเดอร์โหนด
   */
  พรีโพรเซสของฟังก์ชันสาธารณะ (อาร์เรย์ &$ ตัวแปร) {
    ถ้า ('เต็ม' === $ตัวแปร['view_mode']) {
      $this->preprocessFull($ตัวแปร);
    }
  }

  /**
   * บทความประเภทโหนดประมวลผลล่วงหน้าในโหมดดูเต็ม
   *
   * @param อาร์เรย์ $ตัวแปร
   * อาร์เรย์ของตัวแปรที่ใช้ในการเรนเดอร์โหนด
   */
  ฟังก์ชั่นป้องกัน preprocessFull (อาร์เรย์ & $ ตัวแปร) {
    $node = $variables['โหนด'];

    $related_articles = $node->get('related_articles')->referencedEntities();
    $themes = $node->get('themes')->referencedEntities();
    $cultures = $node->get('cultures')->referencedEntities();
    $themes_ids = $cultures_ids = [];
    foreach ($ ธีมเป็น $term) {
      $themes_ids[] = $term->id();
    }
    foreach ($ วัฒนธรรมเป็น $term) {
      $cultures_ids[] = $term->id();
    }
    $nb_related_articles = นับ($related_articles);

    ถ้า ($nb_related_articles < ตัวเอง::MAX_RELATED_ARTICLES) {
      $limit = ตัวเอง::MAX_RELATED_ARTICLES - $nb_related_articles;
      $change_boundary = strtotime('-2 ปี');
      $query = $this->nodeStorage->getQuery()
        ->เงื่อนไข ('ประเภท', 'บทความ')
        ->เงื่อนไข ('สถานะ', 1)
        ->condition('nid', $node->id(), '<>')
        ->เงื่อนไข('รายการโปรด', 1)
        ->condition('เปลี่ยน', $changed_boundary, '>=')
        ->ช่วง(0, $จำกัด);
      $or_themes = $or_cultures = $query->orConditionGroup();
      foreach ($themes_ids เป็น $tid) {
        $or_themes->condition('วัฒนธรรม', $tid);
      }
      foreach ($cultures_ids เป็น $tid) {
        $or_cultures->condition('ธีม', $tid);
      }
      $and = $query->andConditionGroup()
        ->เงื่อนไข($or_themes);
      $query->condition($และ);
      $and = $query->andConditionGroup()
        ->เงื่อนไข($or_cultures);
      $query->condition($และ);
      $node_ids = $query->execute();
    }
  }

}

ซึ่งทำให้ฉันได้รับคำถามต่อไปนี้:

เลือก "base_table"."vid" เป็น "vid", "base_table"."nid" เป็น "nid"
จาก "โหนด" "base_table"
INNER JOIN "node_field_data" "node_field_data" บน "node_field_data"."nid" = "base_table"."nid"
INNER JOIN "node__favorite" "node__favorite" ON "node__favorite"."entity_id" = "base_table"."nid"
เข้าร่วมซ้าย "node__cultures" "node__cultures" บน "node__cultures"."entity_id" = "base_table"."nid"
เข้าร่วมซ้าย "node__themes" "node__themes" บน "node__themes"."entity_id" = "base_table"."nid"
เข้าร่วมซ้าย "node__cultures" "node__cultures_2" บน "node__cultures_2"."entity_id" = "base_table"."nid"
เข้าร่วมซ้าย "node__themes" "node__themes_2" บน "node__themes_2"."entity_id" = "base_table"."nid"
WHERE ("node_field_data"."type" = 'บทความ')
และ ("node_field_data"."สถานะ" = 'NODE_PUBLISHED')
และ ("node_field_data"."nid" <> '19533')
AND ("node__favorite"."favorite_value" = '1')
และ ("node_field_data"."เปลี่ยนแปลง" >= '1583280325')
และ (("node__cultures"."cultures_target_id" = '5077') หรือ ("node__themes"."themes_target_id" = '42') หรือ ("node__themes"."themes_target_id" = '38'))
และ (("node__cultures_2"."cultures_target_id" = '5077') หรือ ("node__themes_2"."themes_target_id" = '42') หรือ ("node__themes_2"."themes_target_id" = '38'))
จัดกลุ่มตาม base_table.vid, base_table.nid
ลิมิต 4 ออฟเซ็ต 0

และไม่ใช่สิ่งที่ฉันคาดไว้เนื่องจากฉันต้องการเงื่อนไข AND ระหว่างรหัสวัฒนธรรมและรหัสธีม ฉันต้องการสิ่งที่ชอบ:

และ (("node__cultures"."cultures_target_id" = '5077') และ (("node__themes"."themes_target_id" = '42') หรือ ("node__themes"."themes_target_id" = '38')))

แทน

และ (("node__cultures"."cultures_target_id" = '5077') หรือ ("node__themes"."themes_target_id" = '42') หรือ ("node__themes"."themes_target_id" = '38'))

ดังนั้นคำถามของฉันคือ: มีวิธีใดที่จะบรรลุสิ่งนี้ด้วย And/OrConditionGroup หรือฉันควรใช้ข้อความค้นหาย่อยเพื่อจับคู่รหัสเฉพาะสำหรับทั้งธีมและวัฒนธรรม

Score:1
ธง in

สิ่งหนึ่งที่เล็กน้อยคือคุณใส่รหัสและฟิลด์ของคุณไม่ตรงกันที่นี่:

foreach ($themes_ids เป็น $tid) {
  $or_themes->condition('วัฒนธรรม', $tid); // ควรใช้ฟิลด์ 'ธีม'
}
foreach ($cultures_ids เป็น $tid) {
  $or_cultures->condition('ธีม', $tid); // ควรใช้ฟิลด์ 'วัฒนธรรม'
}

แต่ประเด็นสำคัญอยู่ที่นี่:

$and = $query->andConditionGroup()
  ->เงื่อนไข($or_themes);
$query->condition($และ);
$and = $query->andConditionGroup()
  ->เงื่อนไข($or_cultures);
$query->condition($และ);

คุณกำลังรวมแต่ละเงื่อนไข OR ไว้ในเงื่อนไข AND ของตัวเอง

แต่สิ่งที่คุณต้องการคือหนึ่ง AND เงื่อนไขการรวมสองเงื่อนไข OR ของคุณ:

$and = $query->andConditionGroup()
  ->เงื่อนไข($or_themes)
  ->เงื่อนไข($or_cultures);
$query->condition($และ);

นอกจากนี้ ตามที่ @pmichelazzo กล่าวถึง คุณสามารถ (ควรหรือฉันจะ) ใช้ IN แทนกลุ่มเงื่อนไข OR ของคุณ เช่น

$cultures_and_themes = $query->andConditionGroup()
  ->condition('วัฒนธรรม', $cultures_ids, 'IN')
  ->condition('ธีม', $themes_ids, 'IN');
$query->condition($cultures_and_themes);  
MacSim avatar
um flag
และเนื่องจาก `andConditionGroup()` เป็นพฤติกรรมเริ่มต้น ฉันแค่ต้องการเชื่อมโยงเงื่อนไขเหล่านั้นเข้ากับข้อความค้นหา ฉันจะยอมรับคำตอบของคุณเพราะมันสมบูรณ์กว่าคำตอบของ @pmichelazzo แต่เขาก็พูดถูกเช่นกัน ขอบคุณทุกคน
Score:1
ธง in

การใช้ตัวอย่างข้อมูลที่คุณระบุ (และคาดว่าจะมี) คุณอาจใช้ตัวดำเนินการ IN แทน AND:

AND (("node__cultures"."cultures_target_id" = '5077') และ (("node__themes"."themes_target_id" IN ('42', '38'))

ด้วยวิธีนี้ คุณจะได้รับวัฒนธรรมที่มี ID เป้าหมาย 5077 (เนื่องจากเหมือนกันทั้งคู่) และธีมที่มี ID เป้าหมาย 42 หรือ 38

โพสต์คำตอบ

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