Execute uma consulta com uma condição de campo da entidade com vários valores

14

Eu tenho um tipo de conteúdo que possui um campo de referência de entidade que permite que os usuários adicionem vários termos de taxonomia nesse campo. Estou tentando realizar consultas que capturam nós que possuem um conjunto específico de termos de taxonomia dentro desse campo.

Usar um valor nesse campo funciona bem, assim.

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

Onde 2 é o ID do termo que estou procurando. No entanto, quando tento procurar nós que contenham dois termos específicos,

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

Eu recebo o erro

Número de parâmetro inválido: o número de variáveis ​​associadas não corresponde ao número de tokens:

Eu também tentei

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

O que não falha, mas não fornece os resultados pretendidos. Ele exibe todos os nós que possuem o termo 2 OU termo 8. Em vez do termo 2 E termo 8 conforme pretendido. Como eu executaria uma consulta que verifica se um nó tem vários valores específicos em um campo de referência da entidade?

Matt
fonte

Respostas:

19

Use dois separados 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();

Isso funciona, não importa quantos termos estejam no campo ou em que delta eles estejam.

Editar

Isso resulta neste 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
fonte
Ele tentou um código equivalente acima e ele não retornou valores. Você verificou se esse código funciona?
Eyal
Sim, funciona para o campo padrão de artigo e tags preenchido com várias tags.
4k4 23/01/19
Talvez minha sugestão tenha falhado porque eu a escrevi da seguinte maneira $and->condition('custom_taxonomy', [2], 'IN'):$and->condition('custom_taxonomy', [8], 'IN')
Eyal
3
Isso não importa, apenas testei, também funciona 'IN'. O que faz a diferença são os dois grupos AND separados.
4k4 23/01
3
Bom, não sabia que isso funciona. Faz sentido, pois isso força várias junções internamente.
Berdir 23/01
8

Para fazer consultas complexas conforme solicitado, você precisará usar um grupo de condições e consultar o 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 a documentação QueryInterface :: condition .

Eyal
fonte
1
Eu implementei a resposta, mas por algum motivo não está exibindo os resultados adequados. Se eu usar apenas um dos $ e condições, como [2], 'IN' ou [8], 'IN', ele exibirá os resultados muito bem, mas quando eu uso os dois, não recebo nenhum resultado. Eu tripliquei a verificação para garantir que tenho nós com os dois.
Matt
1
Pensando nisso, não há necessidade do AND conditionGroup porque o entityQuery usa AND por padrão.
Eyal
1
Ok, mudei para apenas usando $ query-> condition (), mas ainda estou tendo o problema de que, ao usar os dois, ele não exibe nenhum resultado.
Matt
1
De acordo com a documentação da condição QueryInterface ::, você pode aplicar condições no delta. Vou atualizar a resposta com um código de exemplo.
Eyal
1
@ Eyal, o grupo de condições AND parece ser redundante, mas realmente ajuda a especificar várias condições para o mesmo campo. Você só precisa colocar cada condição em um grupo AND separado.
4k4 23/01
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
fonte