Điểm:0

Thực hiện Truy vấn thực thể với nhiều điều kiện trường trên các trường được tham chiếu

lá cờ um

Tôi có một loại nút bài viết với trường tham chiếu các bài viết liên quan. Nếu một bài báo có ít hơn 4 tài liệu tham khảo cho lĩnh vực đó, tôi cần tìm kiếm các bài viết khác mà

  • không phải là nút hiện tại
  • đã được cập nhật ít hơn 2 năm trước
  • có hộp kiểm 'yêu thích' được chọn
  • chia sẻ ít nhất một id văn hóa (tham chiếu phân loại) VÀ ít nhất một id chủ đề (tham chiếu phân loại)

Và tôi thực sự đang tự hỏi làm thế nào để thực hiện nhu cầu cuối cùng đó... Dựa trên Thực hiện truy vấn với điều kiện trường thực thể có nhiều giá trị, tôi đã viết đoạn mã sau:

<?php

không gian tên Drupal\my_module\Pre process;

sử dụng Drupal\Core\DependencyInjection\ContainerInjectionInterface;
sử dụng Drupal\Core\Entity\EntityTypeManagerInterface;
sử dụng Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Loại nút tiền xử lý Article.
 */
lớp MyArticle triển khai ContainerInjectionInterface {

  const MAX_RELATED_ARTICLES = 4;

  /**
   * Lưu trữ thuật ngữ phân loại.
   *
   * @var \Drupal\node\NodeStorage
   */
  $nodeStorage được bảo vệ;

  /**
   * Trình tạo lớp.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   * Trình quản lý kiểu thực thể.
   */
  hàm công khai __construct(EntityTypeManagerInterface $entity_type_manager) {
    $this->nodeStorage = $entity_type_manager->getStorage('node');
  }

  /**
   * {@inheritdoc}
   */
  tạo hàm tĩnh công khai (ContainerInterface $container) {
    trả về tĩnh mới (
      $container->get('entity_type.manager')
    );
  }

  /**
   * Bài báo loại nút tiền xử lý.
   *
   * @param mảng biến $
   * Một mảng các biến được sử dụng để hiển thị nút.
   */
  tiền xử lý hàm công khai(mảng &$biến) {
    if ('full' === $variables['view_mode']) {
      $this->preprocessFull($variables);
    }
  }

  /**
   * Bài báo loại nút tiền xử lý ở chế độ xem đầy đủ.
   *
   * @param mảng biến $
   * Một mảng các biến được sử dụng để hiển thị nút.
   */
  tiền xử lý hàm được bảo vệFull(mảng &$biến) {
    $node = $variables['node'];

    $relative_articles = $node->get('relative_articles')->referencedEntities();
    $themes = $node->get('themes')->referencedEntities();
    $cultures = $node->get('cultures')->referencedEntities();
    $themes_ids = $cultures_ids = [];
    foreach ($themes as $term) {
      $themes_ids[] = $term->id();
    }
    foreach ($cultures as $term) {
      $cultures_ids[] = $term->id();
    }
    $nb_liên quan_articles = đếm($liên quan_bài viết);

    if ($nb_relative_articles < self::MAX_RELATED_ARTICLES) {
      $limit = self::MAX_RELATED_ARTICLES - $nb_relative_articles;
      $changed_boundary = strtotime('-2 năm');
      $query = $this->nodeStorage->getQuery()
        ->điều kiện('loại', 'bài viết')
        ->điều kiện('trạng thái', 1)
        ->điều kiện('nid', $node->id(), '<>')
        -> điều kiện ('yêu thích', 1)
        ->điều kiện('đã thay đổi', $changed_boundary, '>=')
        ->phạm vi(0, giới hạn $);
      $or_themes = $or_cultures = $query->orConditionGroup();
      foreach ($themes_ids as $tid) {
        $or_themes->condition('cultures', $tid);
      }
      foreach ($cultures_ids as $tid) {
        $or_cultures->condition('themes', $tid);
      }
      $and = $query->andConditionGroup()
        ->điều kiện($or_themes);
      $truy vấn->điều kiện($và);
      $and = $query->andConditionGroup()
        ->điều kiện($or_cultures);
      $truy vấn->điều kiện($và);
      $node_ids = $query->execute();
    }
  }

}

mang lại cho tôi truy vấn sau:

CHỌN "base_table".."vid" NHƯ "vid", "base_table".."nid" NHƯ "nid"
TỪ "nút" "base_table"
INNER THAM GIA "node_field_data" "node_field_data" BẬT "node_field_data".."nid" = "base_table".."nid"
INNER THAM GIA "node__favorite" "node__favorite" BẬT "node__favorite".."entity_id" = "base_table".."nid"
THAM GIA TRÁI "node__cultures" "node__cultures" TRÊN "node__cultures".."entity_id" = "base_table".."nid"
THAM GIA TRÁI "node__themes" "node__themes" BẬT "node__themes".."entity_id" = "base_table".."nid"
THAM GIA TRÁI "node__cultures" "node__cultures_2" BẬT "node__cultures_2".."entity_id" = "base_table".."nid"
THAM GIA TRÁI "node__themes" "node__themes_2" BẬT "node__themes_2".."entity_id" = "base_table".."nid"
WHERE ("node_field_data".."type" = 'bài viết')
VÀ ("node_field_data".."status" = 'NODE_PUBLISHED')
AND ("node_field_data".."nid" <> '19533')
VÀ ("node__favorite".."favorite_value" = '1')
VÀ ("node_field_data".."đã thay đổi">= '1583280325')
VÀ (("node__cultures".."cultures_target_id" = '5077') hoặc ("node__themes".."themes_target_id" = '42') hoặc ("node__themes".."themes_target_id" = '38'))
VÀ (("node__cultures_2".."cultures_target_id" = '5077') hoặc ("node__themes_2".."themes_target_id" = '42') hoặc ("node__themes_2".."themes_target_id" = '38'))
NHÓM THEO base_table.vid, base_table.nid
GIỚI HẠN 4 BÙA 0

Và đó không phải là điều tôi mong đợi vì tôi cần điều kiện AND giữa id văn hóa và id chủ đề. Tôi sẽ cần một cái gì đó như:

AND (("node__cultures".."cultures_target_id" = '5077') AND (("node__themes".."themes_target_id" = '42') hoặc ("node__themes".."themes_target_id" = '38')))

thay vì

VÀ (("node__cultures".."cultures_target_id" = '5077') hoặc ("node__themes".."themes_target_id" = '42') hoặc ("node__themes".."themes_target_id" = '38'))

Vì vậy, câu hỏi của tôi là: có cách nào để đạt được điều này với And/OrConditionGroup hay tôi nên sử dụng các truy vấn phụ để khớp với một số id cụ thể cho cả chủ đề và nền văn hóa?

Điểm:1
lá cờ in

Một điều nhỏ là bạn không khớp id và trường của mình ở đây:

foreach ($themes_ids as $tid) {
  $or_themes->condition('cultures', $tid); // nên sử dụng trường 'chủ đề'
}
foreach ($cultures_ids as $tid) {
  $or_cultures->condition('themes', $tid); // nên sử dụng trường 'văn hóa'
}

Nhưng vấn đề chính là ở đây:

$and = $query->andConditionGroup()
  ->điều kiện($or_themes);
$truy vấn->điều kiện($và);
$and = $query->andConditionGroup()
  ->điều kiện($or_cultures);
$truy vấn->điều kiện($và);

Bạn đang bao bọc từng điều kiện OR trong điều kiện AND của chính nó.

Nhưng những gì bạn muốn là một điều kiện AND bao bọc hai điều kiện OR của bạn:

$and = $query->andConditionGroup()
  ->điều kiện($or_themes)
  ->điều kiện($or_cultures);
$truy vấn->điều kiện($và);

Ngoài ra, như @pmichelazzo đã đề cập, bạn có thể (nên? Tôi sẽ) sử dụng IN thay vì nhóm điều kiện OR của mình, ví dụ:

$cultures_and_themes = $query->andConditionGroup()
  ->điều kiện('nền văn hóa', $culture_ids, 'IN')
  ->điều kiện('chủ đề', $themes_ids, 'IN');
$query->condition($cultures_and_themes);  
MacSim avatar
lá cờ um
và vì `andConditionGroup()` là hành vi mặc định nên tôi chỉ cần xâu chuỗi các điều kiện đó vào truy vấn. Tôi sẽ chấp nhận câu trả lời của bạn vì nó hoàn chỉnh hơn câu trả lời @pmichelazzo nhưng anh ấy cũng đúng. Cảm ơn các bạn
Điểm:1
lá cờ in

Sử dụng đoạn mã mà bạn cung cấp (và dự kiến ​​sẽ có), có lẽ bạn có thể sử dụng toán tử IN thay vì AND:

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

Bằng cách này, bạn có được các nền văn hóa có ID mục tiêu 5077 (vì cả hai đều giống nhau) và các chủ đề có ID mục tiêu 42 HOẶC 38.

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