直升机,
首先,请原谅我的英语,不是很好。我正在将Symfony2应用程序的数据容器迁移到MongoDB,然后再运行MySQL。
我添加了DoctrineMongoDBBundle,“几乎所有东西”都完美无缺。
我在文档之间有一些引用,我希望保留Doctrine ORM提供的“延迟加载”模式。我已经阅读了Doctrine ODM的官方文档,
以及一些解释如何创建关系和定义文档以获得“延迟加载”行为的示例
但我不能让它发挥作用。
在我的情况下,我有两个文件,“旅行”和“注意”,我想保留1:N关系,如下所示:
<?php
namespace MyApp\TravelBundle\Document;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
use Gedmo\Mapping\Annotation as Gedmo;
/**
* Travel
*
* @ODM\Document(collection="travel")
*/
class Travel {
/**
* @var \MyApp\NoteBundle\Document\Note
*
* @ODM\ReferenceMany(targetDocument="\MyApp\NoteBundle\Document\Note", mappedBy="travel", sort={"createdAt"="asc"} )
*/
private $notes;
// more properties ...
public function __construct() {
$this->notes = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add notes
*
* @param \MyApp\NoteBundle\Document\Note $notes
*/
public function addNote(\MyApp\NoteBundle\Document\Note $notes) {
$this->notes[] = $notes;
}
/**
* Remove notes
*
* @param \MyApp\NoteBundle\Document\Note $notes
*/
public function removeNote(\MyApp\NoteBundle\Document\Note $notes) {
$this->notes->removeElement($notes);
}
/**
* Get notes
*
* @return Doctrine\Common\Collections\Collection $notes
*/
public function getNotes() {
return $this->notes;
}
// more methods ...
}
?>
<?php
namespace MyApp\NoteBundle\Document;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
use Symfony\Component\Validator\Constraints as Assert;
use Gedmo\Mapping\Annotation as Gedmo;
/**
* Note
*
* @ODM\Document(collection="note")
*/
class Note
{
/**
* @var \MyApp\TravelBundle\Document\Travel
*
* @ODM\ReferenceOne(targetDocument="MyApp\TravelBundle\Document\Travel", inversedBy="notes")
*/
private $travel;
// more properties ...
/**
* Set travel
*
* @param \MyApp\TravelBundle\Document\Travel $travel
* @return Note
*/
public function setTravel(\MyApp\TravelBundle\Document\Travel $travel) {
$this->travel = $travel;
$travel->addNote($this);
return $this;
}
// more methods ...
}
?>
当我在旅行中添加注释时,我理解旅行证件的结果应为:
{ "_id" : ObjectId( "5183aa63095a1a3921000000" ),
"name" : "First travel",
"isActive" : true,
"createdAt" : Date( 1367583331000 ),
"updatedAt" : Date( 1367583331000 ),
"notes" : [{ "$ref" : "note",
"$id" : ObjectId( "5183aa63095a1a3955000000" ),
"$db" : "mydb" }]
}
并且注释文件应该是:
{ "_id" : ObjectId( "5183aa63095a1a3955000000" ),
"travel" : { "$ref" : "travel",
"$id" : ObjectId( "5183aa63095a1a3921000000" ),
"$db" : "mydb" },
"note" : "First note",
"createdAt" : Date( 1367583331000 ),
"updatedAt" : Date( 1367583331000 ) }
但是现在我只在注释文档中获得引用,而旅行文档中没有引用,当我在旅行文档中查询时,Doctrine不会加载相关的注释文档:
<?php
.
.
$travel = $dm->getRepository('TravelBundle:Travel')->findCurrentTravel($user->getId());
$travel->getNotes(); // IS EMPTY :(
.
.
?>
我在旅行中添加注释的过程如下:
<?php
namespace MyApp\TravelBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class TravelController extends Controller {
public function createNoteAction(Request $request) {
$dm = $this->get('doctrine.odm.mongodb.document_manager');
$travel = $dm->getRepository('TravelBundle:Travel')->findCurrentTravel($user->getId());
$entity = new Note();
$form = $this->createForm(newNoteType(), $entity);
if ($request->isMethod('POST')) {
$form->bind($request);
if ($form->isValid()) {
$entity->setTravel($travel);
$dm>persist($travel);
$dm>persist($entity);
$dm>flush();
}
}
}
}
?>
获取方法$ travel-&gt; getNotes()的任何想法或建议都可以通过“延迟加载”自动检索引用的注释。
非常感谢您的贡献,
扎卡里亚斯
答案 0 :(得分:2)
只需移除mappedBy
属性的ReferenceOne
中的$travel
属性即可实现您想要实现的目标:
@ODM\ReferenceMany(targetDocument="\MyApp\NoteBundle\Document\Note", sort={"createdAt"="asc"} )
通过这种方式,doctrine会将Notes标识存储在$nodes
数组中。
使用“mappedBy”代替,Doctrine 不会在$notes
数组中存储Notes的ID ,而是会执行这样的查询来获取实际的注释:
db.Notes.find({travel.$id: <travelId>});
请注意,恕我直言这是首选方法,因为这样当您添加/删除注释时,您不必更新Travel文档。 (但是你必须在$ travel字段上添加一个索引)
另请注意,对于ReferenceMany
,使用mappedBy
是懒惰的:只有当您尝试循环$notes
数组时,它才会实际执行查询,因此它也是轻量级的。 / p>
有关详细信息,请参阅doc。