Search code examples
symfonydoctrinedoctrine-odm

Doctrine ODM Get By Id with mixed type


I have a collection of mixed type like defined here: http://www.doctrine-project.org/2010/07/20/mixing-types-of-documents.html

/**
 * @Document(collection="my_documents")
 * @DiscriminatorField(fieldName="type")
 * @DiscriminatorMap({"article"="Article", "album"="Album"})
 */
class Article
{
    // ...
}

Album

/**
 * @Document(collection="my_documents")
 * @DiscriminatorField(fieldName="type")
 * @DiscriminatorMap({"article"="Article", "album"="Album"})
 */
class Album
{
    // ...
}

I would like to retrieve any object of that collection with a given Id.

Something like

$object = $dm->find(['Article','Album'], $id);

I can't use that because find take a Document Name. It would be :

$article = $dm->find('Article', $id);
$album = $dm->find('Album', $id);

I have tried to create my own query but it always return null.

$qb = $dm->createQueryBuilder(['Article', 'Album']);
$qb
   ->elemMatch(['id' => $id])
;
$result  = $qb->getQuery()->execute();

Do you have any idea?


Solution

  • The easiest solution is to introduce a parent class from which both Article and Album extend. Thanks to that you'll also be able to specify @DiscriminatorMap once:

    /**
     * @Document(collection="my_documents")
     * @DiscriminatorField(fieldName="type")
     * @DiscriminatorMap({"article"="Article", "album"="Album"})
     * @InheritanceType("SINGLE_COLLECTION")
     */
    abstract class Item {  }
    
    /**
     * @Document()
     */
    class Album extends Item { /* ... */ }
    
    /**
     * @Document()
     */
    class Article extends Item { /* ... */ }
    

    Now whenever you would want to look for documents of both types at a same time you can use:

    $item = $dm->find(Item::class, $id);
    

    Depending on what is stored in the database, $item will come back either as an Article or an Album. Furthermore you can do the same with repository:

    $items = $dm->getRepository(Item::class)->findAll();