在 Doctrine ODM 中获取引用的 id 数组

问题描述 投票:0回答:1

我有一个引用用户的 Company 类:

/**
 * @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;

}
php symfony doctrine-orm doctrine doctrine-odm
1个回答
1
投票

经过调查发现,在初始化集合时会触发查询,以避免稍后对每个文档执行一个查询(原因是我们还不能做得更好,请参阅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 列表的位置。

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

如果对象尚未加载(即它仍未初始化

Proxy
),那么询问该文档的标识符将不会触发额外的查询,这是我的项目中由ODM生成的
Proxy
类的片段:

public function getId()
{
    if ($this->__isInitialized__ === false) {
        return  parent::getId();
    }


    $this->__initializer__ && $this->__initializer__->__invoke($this, 'getId', []);

    return parent::getId();
}

还要稍微扩展一下答案,您可以通过 priming 防止 n+1 问题,这样 ODM 将在一个查询中获取所有引用的文档。

© www.soinside.com 2019 - 2024. All rights reserved.