24

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?

0

4 Answers 4

35

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

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.

8
  • 1
    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. Commented Jan 23, 2017 at 20:12
  • 1
    Thinking about it, there is no need for the AND conditionGroup because the entityQuery uses AND by default. Commented Jan 23, 2017 at 20:14
  • 1
    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. Commented Jan 23, 2017 at 20:18
  • 1
    As per the QueryInterface::condition documentation you can apply conditions on the delta. I'll update the answer with an example code. Commented Jan 23, 2017 at 20:19
  • 1
    @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. Commented Jan 23, 2017 at 20:34
3

Drupal 9 looks like this

$userStorage = $this->entityTypeManager->getStorage('user'); $userQuery = $userStorage->getQuery(); $result_user_ids = $userQuery->accessCheck(FALSE) ->condition('field_user_nodes.target_id', [1,2,4], 'IN') ->condition('status', 1) ->execute(); // Above ^^ return $userStorage->loadMultiple($result_user_ids); 
1
  • 1
    Are you sure this is correct? I tested it with D9.3 and the result is the same as described by the post owner. @4k4 's solution still works though. Commented Jan 27, 2022 at 10:31
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, ]; } 

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.