Skip to content

Embedded documents not updated after changing a remove operation to an update #2767

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
jfortunato opened this issue May 6, 2025 · 0 comments · May be fixed by #2768
Open

Embedded documents not updated after changing a remove operation to an update #2767

jfortunato opened this issue May 6, 2025 · 0 comments · May be fixed by #2768

Comments

@jfortunato
Copy link

Bug Report

Q A
BC Break yes
Version 2.11.0

Summary

After removing a parent document with embedded documents and then changing this removal to an update in an onFlush listener, the embedded document updates are not applied.

Current behavior

After all operations have completed the embedded documents are not updated in the database, although the parent document is.

How to reproduce

#[ODM\Document]
class TestDocument
{
    #[ODM\Id]
    public ?string $id = null;

    #[ODM\Field(type: 'int')]
    public int $removedCount = 0;

    #[ODM\EmbedMany(targetDocument: TestEmbeddedDocument::class)]
    public $embeddedDocuments;

    public function __construct(array $embeddedDocuments)
    {
        $this->embeddedDocuments = new ArrayCollection($embeddedDocuments);
    }

    public function incrementRemovedCount(): void
    {
        $this->removedCount++;
        foreach ($this->embeddedDocuments as $embeddedDocument) {
            $embeddedDocument->removedCount++;
        }
    }
}

#[ODM\EmbeddedDocument]
class TestEmbeddedDocument
{
    #[ODM\Field(type: 'int')]
    public int $removedCount = 0;
}

Populate and remove the documents

// Save the parent document with 1 embedded document, both initialized
// with a `removedCount` of 0.
$document = new TestDocument([new TestEmbeddedDocument()]);
$dm->persist($document);
$dm->flush();

// Sometime later, not necessarily in the same script that initially saves
// the document, remove the document and trigger the event listener.
$dm->remove($document);
$dm->flush();

The event listener that changes the removal operation to an update operation

class MyEventListener
{
    public function onFlush(OnFlushEventArgs $eventArgs): void
    {
        $dm = $eventArgs->getDocumentManager();
        $uow = $dm->getUnitOfWork();

        foreach ($uow->getScheduledDocumentDeletions() as $document) {
            if ($document instanceof TestDocument) {
                // Increment the `removedCount` on both the parent document and
                // the embedded document
                $document->incrementRemovedCount();
                // Re-persist the same document & recompute changeset to change the operation from a
                // removal to an update.
                $dm->persist($document);
                $uow->recomputeSingleDocumentChangeSet($dm->getClassMetadata(TestDocument::class), $document);
            }
        }
    }
}

Expected behavior

After all operations have completed, both the embedded documents as well as the parent document should be updated in the database to have a removedCount of 1. This was the case before the 2.11.x release. What actually happens is that the parent document will have a removedCount of 1 but the embedded document will have a removedCount of 0.

jfortunato added a commit to jfortunato/mongodb-odm that referenced this issue May 15, 2025
After a parent document and its embeds are removed and then subsequently
persisted, the embedded documents didn't get updated. This happened
because the parent document goes through an upsert operation, but
`PersistenceBuilder->prepareUpsertData()` did not handle embedded
associations in the same way that
`PersistenceBuilder->prepareUpdateData()` does. This fixes that issue so
that an upserted parent document handles embed-many's the same was as an
updated parent document.

Fixes doctrine#2767
jfortunato added a commit to jfortunato/mongodb-odm that referenced this issue May 15, 2025
After a parent document and its embeds are removed and then subsequently
persisted, the embedded documents didn't get updated. This happened
because the parent document goes through an upsert operation, but
`PersistenceBuilder->prepareUpsertData()` did not handle embedded
associations in the same way that
`PersistenceBuilder->prepareUpdateData()` does. This fixes that issue so
that an upserted parent document handles embed-many's the same was as an
updated parent document.

Fixes doctrine#2767
@jfortunato jfortunato linked a pull request May 15, 2025 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant