Allow entity queries to query reverse relationships

Created on 28 May 2018, over 6 years ago
Updated 2 July 2024, 6 months ago

Problem/Motivation

Entity queries can follow relationships in conditions. The docs in QueryInterface::condition() provide various examples.

   * @param $field
   *   Name of the field being queried. It must contain a field name, optionally
   *   followed by a column name. The column can be the reference property,
   *   usually "entity", for reference fields and that can be followed
   *   similarly by a field name and so on. Additionally, the target entity type
   *   can be specified by appending the ":target_entity_type_id" to "entity".
   *   Some examples:
   *   - nid
   *   - tags.value
   *   - tags
   *   - tags.entity.name
   *   - tags.entity:taxonomy_term.name
   *   - uid.entity.name
   *   - uid.entity:user.name

One thing this allows you to do is query nodes which are tagged with a taxonomy based on a certain property of the taxonomy (for example its name): $nodeQuery->condition('tags.entity.name', 'foo'). Here tags.entity.name means "follow the entity reference relationship on the tags field, to the term entity, to the name field on the term entity".

Similarly you might have a Node hierarchy in the form of a book where a child node references a parent. Getting all children for a parent based on the parent's Node ID is trivial: $childNodeQuery->condition('parent.entity.nid', $parent_id);

The problem is that in the current entity query system, performing the inverse query is not possible. In case a developer wants to find all the Taxonomy Terms that are referenced in the Node's tags field or to find all Nodes that are a parent of another node, there are currently two sub-optimal choices. 1) Either load and loop through all node's where the field isn't empty or 2) go around the entity query API and use the database API directly.

1) Has the drawback of requiring loading data into memory for things that a database is more than capable of handling efficiently for us
2) Has the drawback that the database query requires knowledge of how fields map to tables and that this doesn't change over time.

It should be possible to use the entity query API to traverse these reverse relationships as well.

Steps to reproduce

Proposed resolution

This issue proposes adding a new query syntax for entity query conditions by adding support for this in Tables::addField(). The syntax comes in the form of a referenced_by keyword which has on the left a field that is being referenced in the entity that's being queried and on the right the field that references it followed by the entity type that field belongs to which then allows selecting on a field of the referencing entity.

For example in case we have a Node of type news for which we want to make an overview of all the tags the current user has access to and that are associated to at least one node, we could do so as follows:

\Drupal::entityTypeManager()
  ->getStorage('taxonomy_term')
  ->getQuery()
  ->accessCheck(TRUE)
  ->condition('tid.referenced_by:field_tags:node.type', 'news')
  ->execute(); 

This may be more useful than simply listing all possible terms of a certain vocabulary when building a filter on an overview page, because it eliminates any terms that would lead to the overview showing no results.

Similarly we can find all nodes that are used as a parent of another node in a book structure:

\Drupal::entityTypeManager()
  ->getStorage('node')
  ->getQuery()
  ->accessCheck(TRUE)
  ->condition('nid.referenced_by:parent:node.parent', NULL, 'IS NOT NULL')
  ->execute(); 

Remaining tasks

  • Write tests
  • Write release notes
  • Create change record

User interface changes

API changes

Data model changes

The entity query API has a new referenced_by operation to traverse an entity_reference relationship in the reverse direction.

Release notes snippet

✨ Feature request
Status

Postponed

Version

11.0 πŸ”₯

Component
EntityΒ  β†’

Last updated about 17 hours ago

Created by

πŸ‡¬πŸ‡§United Kingdom joachim

Live updates comments and jobs are added and updated live.
  • Needs tests

    The change is currently missing an automated test that fails when run with the original code, and succeeds when the bug has been fixed.

Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

Production build 0.71.5 2024