Reputation: 1412
I have a Company class that references users:
/**
* @MongoDB\Document()
*/
class Company {
/* ... */
/**
* @MongoDB\ReferenceMany(targetDocument="Topboard\UserBundle\Document\User", inversedBy="companies")
*/
protected $users;
}
In my controller I need to check if the reference to the user exists in the company and keep only the reference to that user, not other references. I also want to avoid multiple DB requests for users. I just want to check if the id of the references matches $currentUserId
.
public function getCompanyAction($companyId, $currentUserId) {
$dm = $this->get('doctrine_mongodb')->getManager();
$company = $dm->getRepository( 'TopboardAppBundle:Company' )->findOneById( $companyId );
foreach ($company->getUsers() as $user) {
// Foreach will query each user separetly. This is not what I need.
// I need somehow access array of references' ids
// and compare them with the $currentUserId
if($user->getId() !== $currentUserId){
// Remove reference
}
}
return $company;
}
Upvotes: 1
Views: 1238
Reputation: 2966
Upon investigation it turned out that the query is fired when collection is initialized to avoid one query per document later (for reasoning why we can't do better yet see this comment on GH). The case is not lost though, solution is not anywhere near being beautiful, but sometimes OD/RMs requires these when performance needs to come first:
$users = $company->getUsers();
// condition below assumes $company is loaded from db so $users is in fact instance of PersistentCollection(Interface)
if ($users->isInitialized()) {
$ids = $users->map(function($user) {
return $user->getId();
})->toArray();
} else {
$ids = array_map(function($dbRef) {
/* this depends on reference type */
return (string) $dbRef['$id'];
}, $users->getMongoData());
}
You could also just place your logic in places where I'm mapping collections to get list of ids of referenced users.
Original answer that is relevant for single references or unitinitailzed proxies
If object is not loaded yet (i.e. it is still uninitialized Proxy
) then asking for that document's identifier will not trigger additional queries, here is snippet of a Proxy
class generated by ODM in my project:
public function getId()
{
if ($this->__isInitialized__ === false) {
return parent::getId();
}
$this->__initializer__ && $this->__initializer__->__invoke($this, 'getId', []);
return parent::getId();
}
Also to expand answer a bit, you can prevent n+1 problem with priming, this way ODM will fetch all referenced documents in one query.
Upvotes: 1