Выполнить запрос с условием поля сущности с несколькими значениями

14

У меня есть тип контента, который имеет поле ссылки на сущность, которое позволяет пользователям добавлять несколько терминов таксономии в этом поле. Я пытаюсь выполнить запросы, которые захватывают узлы, которые имеют определенный набор терминов таксономии в этом поле.

Использование одного значения в этом поле работает нормально, вот так.

    $query = \Drupal::entityQuery('node')
        ->condition('status', NODE_PUBLISHED)
        ->condition('type', 'custom_type')
        ->condition('custom_taxonomy', 2)
        ->sort('field_last_name', DESC);

Где 2 - идентификатор искомого термина. Однако, когда я пытаюсь найти узлы, которые содержат два конкретных термина, как это,

    $query = \Drupal::entityQuery('node')
        ->condition('status', NODE_PUBLISHED)
        ->condition('type', 'custom_type')
        ->condition('custom_taxonomy', [2,8])
        ->sort('field_last_name', DESC);

Я получаю ошибку

Неверный номер параметра: количество связанных переменных не соответствует количеству токенов:

Я также пытался

    $query = \Drupal::entityQuery('node')
        ->condition('status', NODE_PUBLISHED)
        ->condition('type', 'custom_type')
        ->condition('custom_taxonomy', [2,8], 'IN')
        ->sort('field_last_name', DESC);

Что не подводит, но не дает ожидаемых результатов. Он отображает каждый узел , который имеет либо термин 2 OR термин 8. Вместо того , термин 2 И термин 8 , как предполагалось. Как мне выполнить запрос, который проверяет, имеет ли узел несколько определенных значений в поле ссылки на сущность?

Matt
источник

Ответы:

19

Используйте два отдельных andConditionGroup():

$query = \Drupal::entityQuery('node')
  ->condition('status', NODE_PUBLISHED)
  ->condition('type', 'custom_type');
$and = $query->andConditionGroup();
$and->condition('custom_taxonomy', 2);
$query->condition($and);
$and = $query->andConditionGroup();
$and->condition('custom_taxonomy', 8);
$query->condition($and);
$result = $query->execute();

Это работает независимо от того, сколько терминов в поле или в какой дельте они находятся.

редактировать

Это приводит к этому SQL:

SELECT base_table.vid AS vid, base_table.nid AS nid
FROM 
{node} base_table
INNER JOIN {node_field_data} node_field_data ON node_field_data.nid = base_table.nid
INNER JOIN {node__custom_taxonomy} node__custom_taxonomy ON node__custom_taxonomy.entity_id = base_table.nid
INNER JOIN {node__custom_taxonomy} node__custom_taxonomy_2 ON node__custom_taxonomy_2.entity_id = base_table.nid
WHERE  (node_field_data.status = '1') AND (node_field_data.type = 'custom_type') AND( (node__custom_taxonomy.custom_taxonomy_target_id = '2') )AND( (node__custom_taxonomy_2.custom_taxonomy_target_id = '8') )
4k4
источник
Он попробовал эквивалентный код выше, и он не возвратил значения, вы проверяли, работает ли этот код?
Эяль
Да, это работает для стандартного поля статьи и тегов, заполненного несколькими тегами.
4k4
Может быть, мое предложение провалилось, потому что я написал это так $and->condition('custom_taxonomy', [2], 'IN'),$and->condition('custom_taxonomy', [8], 'IN')
Eyal
3
Это не имеет значения, просто проверил, работает 'IN'тоже. Разница заключается в двух отдельных группах AND.
4k4
3
Хорошо, не знал, что это работает. Имеет смысл, так как это заставляет несколько объединений внутри.
Бердир
8

Для выполнения сложных запросов, как вы просили, вам нужно будет использовать группу условий и запросить дельту.

$query = \Drupal::entityQuery('node');
$query->condition('status', NODE_PUBLISHED)
  ->condition('type', 'custom_type')
  ->condition('custom_taxonomy', [2, 8], 'IN')
  ->condition('custom_taxonomy.%delta', 2, '=')
  ->sort('field_last_name', DESC);
$or = $query->orConditionGroup();
$or->condition('custom_taxonomy.0.target_id', 2);
$or->condition('custom_taxonomy.0.target_id', 8);
$query->condition($or);

Смотрите документацию QueryInterface :: условие .

Эяль
источник
1
Я реализовал ответ, но по некоторым причинам он не отображает правильные результаты. Если я использую только одно из $ и условий, таких как [2], 'IN' или [8], 'IN', то результаты отображаются очень хорошо, но когда я использую оба, я не получаю никаких результатов. Я трижды проверил, чтобы убедиться, что у меня есть узлы, которые имеют оба.
Мэтт
1
Размышляя об этом, нет необходимости создавать условие AND, так как entityQuery использует AND по умолчанию.
Эяль
1
Хорошо, я изменил его на использование только $ query-> condition (), но у меня все еще есть проблема, что при использовании обоих он не отображает никаких результатов.
Мэтт
1
Согласно документации QueryInterface :: condition вы можете применять условия к дельте. Я обновлю ответ с примером кода.
Эяль
1
@Eyal, группа условий AND кажется избыточной, но она действительно помогает указать несколько условий для одного поля. Вам нужно только поместить каждое условие в отдельную группу AND.
4k4
1
$taxonomy_term = 'taxonomy_term';
    $vid = 'name_taxon';
    $terms = $this->entity_type_manager->getStorage($taxonomy_term)
      ->loadTree($vid);

foreach ($terms as $term) {
  $term_data[] = [
    "vid" => $term->vid,
    "name" => $term->name,
  ];
}
Виктор
источник