Skip to main content

Posts

Showing posts from August, 2012

Atomicly update an embedded document with Doctrine MongoDB ODM

I had to deal with an unexpected problem recently. In my setup, I have a Conversation document which contains multiple Message documents embedded inside - a one-to-many mapping basically - and I need to atomically push a new Message when a user replies to a conversation. Below is the initial code that I implemented: public function reply($conversationId, Message $message, $flush = true) { $this->dm->createQueryBuilder($this->class) ->update() ->field('archivers')->unsetField() ->field('repliedBy')->set($message->getUserId()) ->field('repliedBody')->set($message->getBody()) ->field('repliedAt')->set(new \DateTime()) ->field('modifiedAt')->set(new \DateTime()) ->field('messages')->push($message) ->field('id')->equals(new \MongoId($conversationId)) ->getQuery() ->execut...

Updates to managed documents under Doctrine MongoDB ODM

If you update a document returned by Doctrine MongoDB ODM, changes to that document will be flushed to even if you do not call the persist() method on that document. That is because the document returned is a managed document. In fact, the persist() call gets ignored for these managed documents. From the documentation : If X is a preexisting managed document, it is ignored by the persist operation. However, the persist operation is cascaded to documents referenced by X, if the relationships from X to these other documents are mapped with cascade=PERSIST or cascade=ALL. In my case, this recently caused an issue where duplicate embedded documents ended up being pushed into a parent document because I was using and updating the parent document for generating a custom Symfony2 form. Turned out to be a bad idea... If you need to update these type of documents, detach them first.