Search code examples
phpmongodbsymfonydoctrine-odm

Data eager loading in doctrine mongodb


Sorry for my english. I seem to be missing something in the work of doctrine with mongo. I have

/**
 * @MongoDB\MappedSuperclass
 * @MongoDB\DiscriminatorField("type")
 * @MongoDB\DiscriminatorMap({
 *   "hotel"="App\Document\Attributes\HotelAttributes",
 *   "apartment"="App\Document\Attributes\ApartmentAttributes",
*/
abstract class AbstractAttribute 
{
    /**
     * @MongoDB\Id
     * @MongoDB\UniqueIndex()
     */
    protected string $id;
    ...
}

And several classes of descendants, like:

namespace App\Document\Attributes;

use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
/**
 * @MongoDB\Document(collection="attributes")
 * @MongoDB\InheritanceType("SINGLE_COLLECTION")
 * @MongoDB\HasLifecycleCallbacks
 */
class HotelAttributes extends AbstractAttribute
{
    /**
     * @MongoDB\Field(
     *     type="int",
     *     nullable=false,
     *     name="bed_places",
     * )
     */
    protected int $bedPlaces;

And a resource class with a reference to attributes

class Resources
{
    /**
     * @MongoDB\ReferenceOne(
     *     targetDocument=AbstractAttribute::class,
     *     storeAs="dbRefWithDb",
     *     orphanRemoval=true,
     *     cascade={"all"}
     * )
     */
    protected AbstractAttribute $attributes;
    ...
}

The resource is created normally, but when fetching by id, the attributes field is not loaded until I try to access the property directly, i.e .:

$resource = $this->dm->getRepository(Resources::class)->find($id);
$resource->getAttributes() will return:

twig dump

$resource->getAttributes()->getCreated() - will return creation date and all fields.

I have a two questions:

  1. How to make the doctrine automatically load all the data?
  2. How do I specify a repository for an abstract class in my example?

Thanks for the help.


Solution

  • The closest thing to fetch="EAGER" in ODM is a process called "priming references". Contrary to ORM's EAGER this will make two database queries (one for your casual documents you're looking for and another one for their primed references) as there is no feasible way to achieve JOIN-like fetching. You can read more about priming in the docs: https://www.doctrine-project.org/projects/doctrine-mongodb-odm/en/2.2/reference/priming-references.html