在Doctrine ODM

时间:2016-06-29 11:45:54

标签: symfony doctrine-orm doctrine doctrine-odm

我有一个引用用户的公司类:

/**
 * @MongoDB\Document()
 */
class Company {

    /* ... */

    /**
     * @MongoDB\ReferenceMany(targetDocument="Topboard\UserBundle\Document\User", inversedBy="companies")
     */
    protected $users;
}

在我的控制器中,我需要检查公司中是否存在对用户的引用,并仅保留对该用户的引用,而不是其他引用。我还想避免为用户提供多个数据库请求。我只想检查引用的id是否与$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;

}

1 个答案:

答案 0 :(得分:1)

经过调查后发现,初始化集合时会触发查询,以避免以后每个文档进行一次查询(为什么我们不能做得更好但看到this comment on GH)。虽然案例并没有丢失,但解决方案并不是美丽的,但有时OD / RM需要这些才能首先实现性能:

$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());
}

您也可以将逻辑放置在我映射集合的位置,以获取引用用户的ID列表。

与单个引用或unitinitailzed代理相关的原始答案

如果尚未加载对象(即它仍然未初始化Proxy),则要求该文档的标识符不会触发其他查询,这里是由Proxy类生成的public function getId() { if ($this->__isInitialized__ === false) { return parent::getId(); } $this->__initializer__ && $this->__initializer__->__invoke($this, 'getId', []); return parent::getId(); } 类的片段我项目中的ODM:

if( strpos($Towns, $Find) === false ) {
    echo $Towns;
}

另外,为了扩展答案,您可以使用priming来防止n + 1问题,这样ODM将在一个查询中获取所有引用的文档。