6

I have an entity with a user entityReference field, which may contain multiple values. I wish to select using EntityQuery the nodes that do NOT contain the uid in the query.

$query
  ->condition('field_shared_with_user.target_id', $uid, '<>');

This only works to exclude $uid if there is only ONE value in the field. If $uid is present but some other uid is also present, it incorrectly includes this node in the result.

What is the correct syntax for writing a condition for a multiple value field?

The most I can find about writing these queries is here:

https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Entity!Query!QueryInterface.php/function/QueryInterface%3A%3Acondition/8

2
  • 1
    Did you try with NOT IN?
    – apaderno
    Feb 2, 2016 at 19:45
  • 2
    I did try NOT IN; it gives the same result, which makes since because (I think) NOT IN means "the field value is not in the array of values I am inputting": $query ->condition('field_shared_with_user.target_id', [$uid1, $uid2], 'NOT IN'); Feb 3, 2016 at 15:07

3 Answers 3

5

From what I understand the Entity Query will just perform a join operation on the tables, resulting in data like the following:

entity.id | field_user.target
        1 |                 5
        1 |                 6
        2 |                 5

A join condition can limit the rows returned, but restricting by field_user.target <> 6 can only remove the one row (1:6), leaving the 1:5 row remaining. Without a subquery, I don't think there is a way to exclude both rows with entity.id = 1.

Two alternatives:

  • Perform an initial query to find all of the entities that reference the user you would like to filter, and then filter your query by those entity ids (essentially doing your own subquery).
  • Get all results, and filter them in PHP afterwards.
5

gapple put me on the right track (at least a solution for my specific problem), and its a combination of his two ideas.

I needed to query for all the nodes that reference my user, then query for all the entities that match my main query. that gives me two arrays of node ids, and if I array_diff the first from the 2nd, I end up with the array of node ids i want.

so, a separate entityQuery is needed, but its not too computationally expensive in my case, I think.

$my_contacts = \Drupal::entityQuery('node')
  ->condition('type', 'sc_card')
  ->condition('field_shared_with_user.target_id', $user->id())
  ->execute();
$public_contacts = \Drupal::entityQuery('node')
  ->condition('type', 'sc_card')
  ->condition('field_public_directory', true)
  ->execute();
$public_not_in_my_contacts = array_diff($public_contacts, $my_contacts);
1

If you want to check for the lack of a value, you need to use notExists() instead of condition(). There's also an exists().

1
  • 2
    That has nothing to do with the question asked
    – AlxVallejo
    Feb 19, 2018 at 21:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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