Wykonaj zapytanie z warunkiem pola encji o wielu wartościach

14

Mam typ zawartości, który ma pole odniesienia encji, które pozwala użytkownikom dodawać wiele terminów taksonomii w tym polu. Próbuję wykonać zapytania, które pobierają węzły, które mają określony zestaw terminów taksonomicznych w tym polu.

Użycie jednej wartości w tym polu działa dobrze, tak jak to.

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

Gdzie 2 to identyfikator szukanego terminu. Jednak gdy próbuję wyszukać węzły, które zawierają dwa takie specyficzne hasła,

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

Otrzymuję błąd

Nieprawidłowy numer parametru: liczba powiązanych zmiennych nie zgadza się z liczbą tokenów:

Próbowałem też

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

Co nie zawodzi, ale nie zapewnia zamierzonych rezultatów. Wyświetla każdy węzeł, który ma albo termin 2 LUB termin 8. Zamiast terminu 2 AND termin 8 zgodnie z przeznaczeniem. Jak miałbym wykonać zapytanie sprawdzające, czy węzeł ma wiele określonych wartości w polu odwołania do encji?

Matt
źródło

Odpowiedzi:

19

Użyj dwóch osobnych 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();

Działa to bez względu na to, ile terminów znajduje się w polu lub w jakiej delcie są.

Edytować

Wynikiem tego jest 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
źródło
Wypróbował równoważny kod powyżej i nie zwrócił żadnych wartości, czy sprawdziłeś, czy ten kod działa?
Eyal
Tak, działa w przypadku standardowego pola artykułu i tagów wypełnionego wieloma tagami.
4k4
Może moja sugestia się nie powiodła, ponieważ tak napisałem $and->condition('custom_taxonomy', [2], 'IN'),$and->condition('custom_taxonomy', [8], 'IN')
Eyal
3
To nie ma znaczenia, właśnie go przetestowałem, działa 'IN'również z . Różnica polega na dwóch osobnych grupach AND.
4k4
3
Fajnie, nie wiedziałem, że to działa. Ma to sens, ponieważ wymusza to wiele połączeń wewnętrznych.
Berdir
8

Aby wykonać złożone zapytania, tak jak prosiłeś, będziesz musiał użyć grupy warunków i zapytać o różnicę.

$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);

Zobacz dokumentację QueryInterface :: condition .

Eyal
źródło
1
Zaimplementowałem odpowiedź, ale z jakiegoś powodu nie wyświetla ona właściwych wyników. Jeśli użyję tylko jednego z $ i warunków, takich jak [2], „IN” lub [8], „IN” wyświetla wyniki w porządku, ale kiedy używam obu, nie otrzymuję żadnych wyników. Potrójnie sprawdziłem, aby upewnić się, że mam węzły, które mają oba.
Matt
1
Biorąc to pod uwagę, grupa warunków warunku AND nie jest potrzebna, ponieważ jednostkaQuery domyślnie używa AND.
Eyal
1
Okej, zmieniłem go na użycie tylko $ query-> condition (), ale nadal mam problem, że przy użyciu obu nie wyświetla żadnych wyników.
Matt
1
Zgodnie z dokumentacją QueryInterface :: condition można zastosować warunki w delcie. Zaktualizuję odpowiedź przykładowym kodem.
Eyal
1
@Eyal, grupa warunków AND wydaje się zbędna, ale naprawdę pomaga określić wiele warunków dla tego samego pola. Musisz tylko umieścić każdy warunek w osobnej grupie 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,
  ];
}
Viktor
źródło