How to update embedded documents in Doctrine MongoDB?

I have a document with an embedded document. When I create an object for the first time, everything works fine, but when I try to update a document, the embedded document is not 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 request a document, update the values ​​and save 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 install 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, option B works fine. However, in my application, documents are more complicated, and it would be impractical for me to create a new object for an embedded document every time I have to update it. Is there a way to tell Doctrine ODM to look at the values ​​of an embedded document to decide whether to update it?

+6
source share
2 answers

I faced the same problem. It turns out UnitOfWork seems to fail when calculating sets of documents with other embedded documents, although I couldn't figure out why ... As a result, when I compare the actual value and the original, the unit of work shows the same value for both. Speaking with your option A when you

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

The unit of work shows "foo baz" for both the old and the new value and will not recognize it as a change and will not update it.

In any case, this leads 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 causes the work unit to recognize the docB document of the $ document as a newly installed document and will clear it as expected.

+2
source

MongoDB has only atomic operations. You have options: 1. Request a document, find a suitable sub-document, update the entire document or part of it. Pros: simple logic Cons: non-atomic 2. Use the positional $ operator, your subdocuments are in the list.

0
source

Source: https://habr.com/ru/post/924655/


All Articles