Effectuer une requête avec une condition de champ d'entité avec plusieurs valeurs

14

J'ai un type de contenu qui a un champ de référence d'entité qui permet aux utilisateurs d'ajouter plusieurs termes de taxonomie dans ce champ. J'essaie d'exécuter des requêtes qui récupèrent des nœuds qui ont un ensemble spécifique de termes de taxonomie dans ce champ.

Utiliser une valeur dans ce champ fonctionne très bien, comme ça.

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

Où 2 est l'ID du terme que je recherche. Cependant, lorsque j'essaie de rechercher des nœuds contenant deux termes spécifiques comme celui-ci,

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

Je reçois l'erreur

Numéro de paramètre non valide: le nombre de variables liées ne correspond pas au nombre de jetons:

J'ai aussi tenté

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

Ce qui n'échoue pas, mais ne fournit pas les résultats escomptés. Il affiche chaque nœud qui a soit le terme 2 OU le terme 8. Au lieu du terme 2 ET du terme 8 comme prévu. Comment pourrais-je effectuer une requête qui vérifie si un nœud a plusieurs valeurs spécifiques dans un champ de référence d'entité?

Mat
la source

Réponses:

19

Utilisez deux séparés 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();

Cela fonctionne quel que soit le nombre de termes dans le domaine ou dans quel delta ils se trouvent.

Éditer

Il en résulte ce 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
la source
Il a essayé un code équivalent ci-dessus et il n'a retourné aucune valeur, avez-vous vérifié que ce code fonctionne?
Eyal
Oui, cela fonctionne pour le champ d'article et de balises standard rempli de plusieurs balises.
4k4
Peut-être que ma suggestion a échoué parce que je l'ai écrite comme ça $and->condition('custom_taxonomy', [2], 'IN'),$and->condition('custom_taxonomy', [8], 'IN')
Eyal
3
Cela n'a pas d'importance, juste testé, fonctionne 'IN'aussi. Ce qui fait la différence, ce sont les deux groupes ET séparés.
4k4
3
Nice, je ne savais pas que cela fonctionne. Cela a du sens, car cela force les jointures multiples en interne.
Berdir
8

Pour effectuer des requêtes complexes comme vous l'avez demandé, vous devrez utiliser un groupe de conditions et interroger le delta.

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

Voir la documentation QueryInterface :: condition .

Eyal
la source
1
J'ai implémenté la réponse, mais pour une raison quelconque, elle n'affiche pas les bons résultats. Si j'utilise une seule des conditions $ et, comme [2], 'IN' ou [8], 'IN' cela affiche très bien les résultats, mais quand j'utilise les deux, je n'obtiens aucun résultat. J'ai vérifié trois fois pour m'assurer que j'ai des nœuds qui ont les deux.
Matt
1
En y réfléchissant, il n'y a pas besoin de AND conditionGroup car l'entitéQuery utilise AND par défaut.
Eyal
1
D'accord, je l'ai changé en utilisant simplement $ query-> condition () mais j'ai toujours le problème que lors de l'utilisation des deux, il n'affiche aucun résultat.
Matt
1
Selon la documentation QueryInterface :: condition , vous pouvez appliquer des conditions sur le delta. Je mettrai à jour la réponse avec un exemple de code.
Eyal
1
@Eyal, le groupe de conditions AND semble être redondant, mais cela aide vraiment à spécifier plusieurs conditions pour le même champ. Il vous suffit de placer chaque condition dans un groupe ET distinct.
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
la source