简体   繁体   English

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

[英]How do I update embedded documents in Doctrine MongoDB?

I have a document that has a document embedded. 我有一个嵌入了文档的文档。 When I create an object for the first time everything works fine, but when I try to update a document, the embedded document does not get updated. 第一次创建对象时,一切正常,但是当我尝试更新文档时,嵌入式文档不会更新。

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

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

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

In my application I query for a document, update the values and persist them to the data store. 在我的应用程序中,我查询文档,更新值并将其持久保存到数据存储中。

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

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

If I do not update the embedded document, but set a new one everything works fine: 如果我不更新嵌入式文档,而是设置一个新文档,则一切正常:

// 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();

As I said, Variant B works fine. 就像我说的那样,变体B可以正常工作。 However, in my application the documents are more complex and it would be impractical for me to create a new object for the embedded document every time I have to update it. 但是,在我的应用程序中,文档更加复杂,对于每次需要更新嵌入文档的对象来说,这对于我来说都是不切实际的。 Is there a method to tell Doctrine ODM to look at the values of an embedded document to decide if it should be updated? 有没有一种方法可以让Doctrine ODM查看嵌入式文档的值来决定是否应该对其进行更新?

I faced exactly the same issue. 我面临着完全相同的问题。 It turns out the UnitOfWork seems to fail in computing the changesets of documents with other documents embedded, though I have not been able to figure out why... As a result, when when i compare the actual value and the original one, unit of work shows the same value for both. 事实证明,UnitOfWork似乎无法计算嵌入了其他文档的文档的变更集,尽管我无法弄清原因...因此,当我比较实际值和原始值时,单位为作品对两者显示出相同的价值。 Speaking with your Variant A, when you 当您与变体A说话时

$document->getDocB()->setValueB('foo baz');

Unit of work shows "foo baz" for both the old and the new value and will not recognize it as aa change and will therefor not update it. 工作单位对于新旧值均显示“ foo baz”,并且不会将其识别为更改,因此不会对其进行更新。

Anyway, this leeds to a workaround: 无论如何,这导致一种解决方法:

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

This makes the unit of work recognize the docB of $document as a newly set document and will flush it as expected. 这使工作单元将$ document的docB识别为新设置的文档,并将按预期刷新它。

MongoDB has only atomic operations. MongoDB只有原子操作。 You have options: 1. Query the document, find the apropriate subdocument, update the whole document or its part. 您有以下选择:1.查询文档,找到适当的子文档,更新整个文档或其一部分。 Pros: easy logic Cons: non-atomic 2. Use positional $ operator is your subdocuments are in list. 优点:简单的逻辑缺点:非原子性的2.使用位置$运算符是您的子文档在列表中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM