11

I have a content type that has a entity reference field that allows users to add multiple taxonomy terms in that field. I'm attempting to perform queries that grab nodes that have a specific set of taxonomy terms within that field.

Using one value in that field works fine, like so.

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

Where 2 is the id of the term I'm searching for. However when I attempt to search for nodes that contain two specific terms like so,

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

I receive the error

Invalid parameter number: number of bound variables does not match number of tokens:

I've also attempted

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

Which doesn't fail, but doesn't provide the intended results. It displays every node that has either term 2 OR term 8. Instead of term 2 AND term 8 as intended. How would I perform a query that checks if a node has multiple specific values in an entity reference field?

17

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

This works no matter how many terms are in the field or in which delta they are.

Edit

This results in this 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') )
  • He tried an equivalent code above and it returned no values, did you check that this code works? – Eyal Jan 23 '17 at 20:54
  • Yes, it works for the standard article and tags field filled with multiple tags. – 4k4 Jan 23 '17 at 20:55
  • Maybe my suggestion failed because I wrote it like so $and->condition('custom_taxonomy', [2], 'IN'), $and->condition('custom_taxonomy', [8], 'IN') – Eyal Jan 23 '17 at 20:57
  • 3
    That doesn't matter, just tested it, works with 'IN' too. What makes the difference is the two separate AND groups. – 4k4 Jan 23 '17 at 21:02
  • 2
    Nice, didn't know this works. Makes sense, as this forces multiple joins internally. – Berdir Jan 23 '17 at 21:33
6

To do complex queries as you asked, you will need to use a condition group and to query the 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);

See QueryInterface::condition documentation.

  • I implemented the answer, but for some reason it's not displaying the proper results. If I use only one of the $and conditions, like [2], 'IN' or [8], 'IN' it displays the results just fine, but when I use both, I don't get any results. I triple checked to make sure I have nodes that have both. – Matt Jan 23 '17 at 20:12
  • Thinking about it, there is no need for the AND conditionGroup because the entityQuery uses AND by default. – Eyal Jan 23 '17 at 20:14
  • Okay I changed it to just using $query->condition() but I'm still having the issue that when using both it doesn't display any results. – Matt Jan 23 '17 at 20:18
  • As per the QueryInterface::condition documentation you can apply conditions on the delta. I'll update the answer with an example code. – Eyal Jan 23 '17 at 20:19
  • @Eyal, the AND condition group seems to be redundant, but it really helps to specify multiple conditions for the same field. You only need to put each condition in a separate AND group. – 4k4 Jan 23 '17 at 20:34
0

$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,
  ];
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.