Using Doctrine's MongoDB ODM - How do I find documents by embedded documents' fields?
Asked Answered
G

2

5

I have the following Documents:

  • A User document.
  • An embedded document, containing a reference to (see next document)
  • a Site document

Each user has an array of embedded documents inside, each representing an item he follows - a site, a twitter account - with the option to mark specific categories he's interested in. Each embedded document has a reference to the third document - the Site document (or Twitter document, etc..).

The question is - using the MongoDB ODM, how can I get the documents of all the users that chose to follow a given site, using the id of that site ?
(see below (after the files) how it is done in the mongodb shell)

User.php

<?php
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;

/**
 * @ODM\Document
 */

class User {
    /**
     * @ODM\Id
     * @var string
     */
    protected $id;

    /**
     * @ODM\EmbedMany(
     *      discriminatorMap={
     *          "site"="SiteFollow",
     *          "twitter"="TwitterFollow",
     *      }
     *  )
     * @var ArrayCollection;
     */
    protected $follows;
}

SiteFollow.php

<?php
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;

/**
 * @ODM\EmbeddedDocument
 */

class SiteFollow {
    /**
     * @ODM\Collection
     * @var array
     */
    protected $interestingCategories;

    /**
     * @ODM\ReferenceOne(targetDocument="Site", simple=true)
     * @var Site
     */
    protected $siteItem;
}

Site.php

<?php
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;

/**
 * @ODM\Document
 */

class Site {
    /**
     * @ODM\Id
     * @var string
     */
    protected $id;

    /**
     * @ODM\String
     * @var string
     */
    protected $name;

    /**
     * @ODM\String
     * @var string
     */
    protected $url;
}

An example for a user document in the mongo shell:

db.User.findOne()
{
    "_id": ObjectId("123"),
    "follows": [
        {
            "interestingCategories": [
                "PHP"
            ]
            "siteItem" : ObjectId("OBJECT_ID_OF_SITE_DOCUMENT"),
            "_doctrine_class_name" : "site"
        }
    ]
}

Mongo shell command for getting all the users that are following a specific site:

db.User.find({"follows.siteItem": ObjectId("OBJECT_ID_OF_SITE_DOCUMENT")})
Glaive answered 6/3, 2013 at 12:56 Comment(2)
Does this help you: phpntips.com/…Surety
Try this: $builder->Field ('follows. siteItem')->getQuery()->execute();Orlena
S
7

I found that answer provided by Madarco sometimes doesn't work properly. If you are querying for the $id field of the reference field in embedded document you may need to pass MongoId object to the equals() method. So in this case it would be:

$repo = $odm->getRepository('User');
$repo->createQueryBuilder()
    ->field('follows.siteItem.$id')
    ->equals(new \MongoId($siteId))
    ->getQuery()
    ->execute();
Spermatozoon answered 21/11, 2014 at 7:56 Comment(0)
S
1

Just query for the $id field of the DbRef field siteItem in the SiteFollow document (which is in an embedded collection in the User document):

$repo = $odm->getRepository("User");
$repo->createQueryBuilder()
         ->field("follows.siteItem.$id")
         ->equals($siteId)
         ->getQuery()
         ->execute();
Starling answered 4/12, 2013 at 16:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.