Realizar una consulta con una condición de campo de entidad con múltiples valores

14

Tengo un tipo de contenido que tiene un campo de referencia de entidad que permite a los usuarios agregar múltiples términos de taxonomía en ese campo. Estoy intentando realizar consultas que captan nodos que tienen un conjunto específico de términos de taxonomía dentro de ese campo.

Usar un valor en ese campo funciona bien, así.

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

Donde 2 es la identificación del término que estoy buscando. Sin embargo, cuando intento buscar nodos que contienen dos términos específicos como este,

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

Recibo el error

Número de parámetro no válido: el número de variables enlazadas no coincide con el número de tokens:

También he intentado

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

Lo que no falla, pero no proporciona los resultados previstos. Muestra todos los nodos que tienen el término 2 O el término 8. En lugar del término 2 Y el término 8 según lo previsto. ¿Cómo realizaría una consulta que verifique si un nodo tiene múltiples valores específicos en un campo de referencia de entidad?

Mate
fuente

Respuestas:

19

Use dos por separado 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();

Esto funciona sin importar cuántos términos haya en el campo o en qué delta estén.

Editar

Esto da como resultado este 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
fuente
Intentó un código equivalente arriba y no devolvió valores, ¿verificó que este código funciona?
Eyal el
Sí, funciona para el artículo estándar y el campo de etiquetas lleno de múltiples etiquetas.
4k4
Tal vez mi sugerencia falló porque la escribí como tal $and->condition('custom_taxonomy', [2], 'IN'),$and->condition('custom_taxonomy', [8], 'IN')
Eyal
3
Eso no importa, solo lo probé, también funciona 'IN'. Lo que hace la diferencia son los dos grupos AND separados.
4k4
3
Bien, no sabía que esto funciona. Tiene sentido, ya que esto obliga a múltiples uniones internas.
Berdir el
8

Para realizar consultas complejas como solicitó, deberá utilizar un grupo de condiciones y consultar el 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);

Consulte la documentación de QueryInterface :: condition .

Eyal
fuente
1
Implementé la respuesta, pero por alguna razón no muestra los resultados adecuados. Si uso solo uno de los $ y las condiciones, como [2], 'IN' u [8], 'IN' muestra los resultados muy bien, pero cuando uso ambos, no obtengo ningún resultado. Revisé tres veces para asegurarme de que tengo nodos que tienen ambos.
Matt
1
Pensando en ello, no hay necesidad de AND conditionGroup porque entityQuery usa AND por defecto.
Eyal
1
De acuerdo, lo cambié a solo usando $ query-> condition () pero todavía tengo el problema de que cuando uso ambos no muestra ningún resultado.
Matt
1
Según la documentación de QueryInterface :: condition , puede aplicar condiciones en el delta. Actualizaré la respuesta con un código de ejemplo.
Eyal el
1
@Eyal, el grupo de condiciones AND parece ser redundante, pero realmente ayuda a especificar múltiples condiciones para el mismo campo. Solo necesita poner cada condición en un grupo AND separado.
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
fuente