Score:1

Is it possible to use a subquery in an entity query?

ai flag

How can I add a condition to a Drupal 9 entity query using another entity query on a different entity type?

I'll illustrate the question by describing one specific use case, though I don't think it would be difficult to come up with any number of plausible use cases.

The application for this use case tracks articles in published medical literature. An article is represented by a custom entity type which tracks when it was imported into the system, whether the full text for the article has been obtained, which topics have been assigned to the article for which review cycles, when and in which journal was it published, and lots of other information.

A second custom entity type exists to represent batches ("packets") of articles assigned for review, tracking when the batches were assigned, for which topics, and to which oncology specialists, as well as what the results of those reviews were. An article can be assigned to many review packets, each with multiple assigned reviewers, and each review packet can request reviews for any number of articles.

The search module for this application has a requirement that articles can be searched for based on many different criteria, most of which can be applied by inspecting the Article entities, but some of which can only be implemented by looking at values in the Packet entities. An example search might, for example, request to find all articles published within the past twelve months in journal J, and assigned for review by reviewer R.

In a CMS more suited to working directly with the relational SQL tables it would be very straightforward to support such a search using a couple of table joins. But Drupal makes that approach less appealing, as we have no documented guarantee that the table and column naming conventions underneath entities can be relied on not to change.

I could create and execute two separate entity queries and use the results of the second to weed out results returned by the first query which are not also present in the results of the second. But among the drawbacks of this approach is the fact that it breaks the Drupal paging mechanism.

I could try to mimic what the DBMS would be doing much more efficiently by feeding the entity IDs returned by the second query into a condition on the first query, but who knows what internal limits that might run into when the results of the second query are huge?

I could implement a kludge to denormalize the data, storing entity references from the Article entities back to the Packet entities which are in turn pointing back to the Article entities, but we all know the problems with trying to keep the same information in multiple places in sync.

If all the searches were for articles assigned for review, I could turn things around and use an entity query on the Packet type, following its reference to Article entities for the other criteria which need to be tested. But a large percentage of the searches are meant to find articles whether or not they have been assigned for review. So for this path I'd have to implement two separate sets of search logic in parallel, one for searches which involve assignment to review packets and a second for searches which don't care about assignment for review. And this approach still wouldn't address searches looking explicitly for articles which have not been assigned for review. And bear in mind, I'm keeping this use case example simple by restricting it to only two entity types.

Googling (and searching this forum) keeps diverting me to information on using the underling database query APIs instead of the entity query system, at least with the query terms I'm using.

Is there a way to use a subquery (or even better, join to another entity type) in the entity query APIs? If not, are there prospects for supporting such functionality under discussion in Drupal Valhalla?

cn flag
For complicated searches involving multiple entity types, [Search API](https://www.drupal.org/project/search_api) and [Search API Solr](https://www.drupal.org/project/search_api_solr) are a great solution that give you full control to build the index however you like. Of course, the huge downside to this is that you also have to set up Solr.
ai flag
Thanks, @Patrick. I'll take a look.
in flag
Search API is a good suggestion. By doing so, you'll be working with a View, rather than an entity query. You can additionally augment your project by using entity bundles and Entity Reference fields. I didn't see you mention if you had done so, but it might be helpful to start by defining all of your entities as bundles of one single entity type. Your view will then be able to drill down on all of the bundle types at once. Entity Reference fields will allow for creating explicit relationships between entities; use the field's cardinality to establish a one-to-one or one-to-many relationship.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.