我有一个引用用户的公司类:
/**
* @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;
}
答案 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将在一个查询中获取所有引用的文档。