1

What's the most performant way to get reverse related entries within an Element Query?

Here's a contrived example of this.

I have thousands of "book" entries and thousands of "collection" entries. I need to generate a list of all the books and present a comma separated list of the collections it appears in. Some books might be in 10 collections, some might be in 50+.

Unfortunately, the code below creates the n+1 query problem. But I can't eager load this because this is a reverse relationship.

How could I achieve this in a more performant way?

<?php

$query = Entry::find()
    ->section('books')
    ->all();

foreach ($query as $book) {
  $data[] = [
    "title" => $book->title,
    "author" => $book->authorName,
    "inCollections" => $this->_getBookCollections($book)
  ];
}

// ... later in the class

private function _getBookCollections($book)
{
    $query = Entry::find()
      ->section('collections')
      ->relatedTo($book)
      ->all();

    return implode(", ", ArrayHelper::getColumn($query, "title"));
}
  • 1
    Can't copy/write the code right now but the "best" way would be to create a custom behavior that enables you to eager load them directly as Crafts default eager loading does. The only reason you can't perform it by default is because your entry doesn't contain the field so there is no property to store the elements thus using a behavior will help you out. I'll post a more detailed answer on Monday – Robin Schambach Mar 29 at 21:26
  • Thanks for the heads up, @RobinSchambach! Yeah, if you don't mind sharing an example of such a thing when you get time that would be awesome. Really appreciate it! – Aaron Bushnell Mar 30 at 1:37

Your Answer

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

Browse other questions tagged or ask your own question.