Führen Sie eine Abfrage mit einer Entitätsfeldbedingung mit mehreren Werten durch

14

Ich habe einen Inhaltstyp mit einem Entitätsreferenzfeld, mit dem Benutzer diesem Feld mehrere Taxonomiebegriffe hinzufügen können. Ich versuche, Abfragen durchzuführen, die Knoten mit einem bestimmten Satz von Taxonomiebegriffen in diesem Feld erfassen.

Die Verwendung eines Werts in diesem Feld funktioniert wie folgt.

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

Wobei 2 die ID des gesuchten Begriffs ist. Wenn ich jedoch versuche, nach Knoten zu suchen, die zwei bestimmte Begriffe wie diesen enthalten,

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

Ich erhalte den Fehler

Ungültige Parameternummer: Anzahl der gebundenen Variablen stimmt nicht mit der Anzahl der Token überein:

Ich habe es auch versucht

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

Was nicht scheitert, aber nicht die beabsichtigten Ergebnisse liefert. Es zeigt jeden Knoten an, der entweder Term 2 ODER Term 8 hat. Anstelle von Term 2 UND Term 8, wie beabsichtigt. Wie führe ich eine Abfrage durch, mit der überprüft wird, ob ein Knoten mehrere bestimmte Werte in einem Entitätsreferenzfeld enthält?

Matt
quelle

Antworten:

19

Verwenden Sie zwei separate 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();

Dies funktioniert unabhängig davon, wie viele Terme sich auf dem Gebiet befinden oder in welchem ​​Delta sie sich befinden.

Bearbeiten

Dies führt zu dieser 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
quelle
Er hat oben einen entsprechenden Code ausprobiert und es wurden keine Werte zurückgegeben. Haben Sie überprüft, ob dieser Code funktioniert?
Eyal
Ja, es funktioniert für das Standardfeld für Artikel und Tags, das mit mehreren Tags gefüllt ist.
4. April,
Vielleicht scheiterte mein Vorschlag , weil ich es mag , so schrieb $and->condition('custom_taxonomy', [2], 'IN'),$and->condition('custom_taxonomy', [8], 'IN')
Eyal
3
Das ist egal, nur getestet, funktioniert auch mit 'IN'. Was den Unterschied ausmacht, sind die beiden UND-Gruppen.
4. April,
3
Schön, wusste nicht, dass das funktioniert. Sinnvoll, da dies intern mehrere Joins erzwingt.
Berdir
8

Um komplexe Abfragen wie gewünscht durchzuführen, müssen Sie eine Bedingungsgruppe verwenden und das Delta abfragen.

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

Siehe Dokumentation zu QueryInterface :: condition .

Eyal
quelle
1
Ich habe die Antwort implementiert, aber aus irgendeinem Grund werden nicht die richtigen Ergebnisse angezeigt. Wenn ich nur eine der $ und Bedingungen wie [2], 'IN' oder [8], 'IN' verwende, werden die Ergebnisse einwandfrei angezeigt, aber wenn ich beide verwende, erhalte ich keine Ergebnisse. Ich überprüfte dreimal, um sicherzustellen, dass ich Knoten habe, die beide haben.
Matt
1
Wenn Sie darüber nachdenken, ist die AND conditionGroup nicht erforderlich, da die entityQuery standardmäßig AND verwendet.
Eyal
1
Okay, ich habe es so geändert, dass nur $ query-> condition () verwendet wird, aber ich habe immer noch das Problem, dass bei Verwendung von beiden keine Ergebnisse angezeigt werden.
Matt
1
Gemäß der Query - Interface :: Zustand Dokumentation können Sie Bedingungen auf dem Delta gelten. Ich werde die Antwort mit einem Beispielcode aktualisieren.
Eyal
1
@Eyal, die AND-Bedingungsgruppe scheint redundant zu sein, aber es ist wirklich hilfreich, mehrere Bedingungen für dasselbe Feld anzugeben. Sie müssen nur jede Bedingung in eine separate AND-Gruppe einfügen.
4. April,
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
quelle