如何更新Doctrine MongoDB中的嵌入式文档?

时间:2012-09-05 16:20:40

标签: php mongodb doctrine doctrine-odm

我有一个嵌入了文档的文档。当我第一次创建一个对象时,一切正常,但是当我尝试更新文档时,嵌入的文档不会更新。

/** @MongoDB\Document */
class DocumentA
{
    /** @MongoDB\EmbedOne(targetDocument="DocumentB") **/
    protected $docB;

    /** @MongoDB\String */
    protected $valueA;
}

/** @MongoDB\EmbeddedDocument */
class DocumentB
{
    /** @MongoDB\String */
    protected $valueB;
}

在我的应用程序中,我查询文档,更新值并将它们保存到数据存储中。

// Variant A – Does not work
$document = ... // find from data store
$document->setValueA('Hello World');
$document->getDocB()->setValueB('foo baz');

$om->persist($document);
$om->flush();

如果我不更新嵌入式文档,但设置一个新文件,一切正常:

// Variant B - Does work
$document = ... // find from data store
$document->setValueB('Hello World 2');
$document->setDocB(new DocumentB());
$document->getDocB()->setValueB('foo baz 2');

$om->persist($document);
$om->flush();

正如我所说,变体B的工作正常。但是,在我的应用程序中,文档更复杂,每次我必须更新它时,为嵌入式文档创建一个新对象是不切实际的。是否有方法告诉Doctrine ODM查看嵌入文档的值以决定是否应该更新它?

2 个答案:

答案 0 :(得分:2)

我遇到了完全相同的问题。事实证明,UnitOfWork在计算嵌入了其他文档的文档更改集时似乎失败了,尽管我还没弄清楚为什么...... 因此,当我比较实际值和原始值时,工作单元显示两者的相同值。当您

时,与您的变体A说话
$document->getDocB()->setValueB('foo baz');

工作单元显示旧值和新值的“foo baz”,并且不会将其识别为更改,因此不会更新它。

无论如何,这导致了一种解决方法:

$document = ... // find from data store
$document->setValueA('Hello World');
$docB = $document->getDocB();
$docB->setValueB('foo baz');
$om->detach($docB);
$om->persist($document);
$om->flush();

这使得工作单元将$ document的docB识别为新设置的文档,并按预期将其刷新。

答案 1 :(得分:0)

MongoDB只有原子操作。 你有选择: 1.查询文档,找到合适的子文档,更新整个文档或其中的部分。 优点:简单的逻辑 缺点:非原子的 2.使用位置$运算符是您的子文档在列表中。