在Doctrine MongoDB中删除该对象时,如何删除对象的任何引用?

时间:2022-04-11 09:16:21

I'm getting the following critical error on my page

我的页面上出现以下严重错误

The "WildkatProxy\DocumentsTagProxy" document with identifier "4e90eede17bc2ec68c000001" could not be found.

I'm assuming this is because the Documents Tag Proxy has been deleted from another action, and so the reference is no longer valid. I now want to delete the stale reference to this object, but silently. (As this could happen in a lot of other situations too) Is there anyway I can do a "reverse cascade" on all objects referencing the deleted object when the object is deleted?

我假设这是因为文档标记代理已从其他操作中删除,因此引用不再有效。我现在想要删除对该对象的陈旧引用,但是要静默。 (因为这可能会在很多其他情况下发生)无论如何,当删除对象时,我是否可以对引用已删除对象的所有对象执行“反向级联”?

What are best practices for accomplishing this?

完成此任务的最佳做法是什么?

Thanks Andy

2 个解决方案

#1


1  

I assume you have two collections, ArticleTag and Article in which articles have references to article tags. If you want to delete tag references from articles when a tag is removed you can implement an event listener.

我假设您有两个集合,ArticleTag和Article,其中的文章引用了文章标签。如果要在删除标记时从文章中删除标记引用,则可以实现事件侦听器。

Create a class:

创建一个类:

namespace Foo\BarBundle\EventListener;

use Doctrine\ODM\MongoDB\Event\LifecycleEventArgs;
use Foo\BarBundle\Document\Article;

class ArticleTagRemovalListener
{
    public function preRemove(LifecycleEventArgs $args)
    {
        $document = $args->getDocument();

        if ($document instanceof Article) {
            // Remove tag from all articles
            $args
                ->getDocumentManager()
                ->getRepository('FooBarBundle:Article')
                ->removeTag($document);
        }
    }
}

And register this class in your services.yml or xml file:

并在services.yml或xml文件中注册此类:

foo_bar.listener.tag_removal:
    class: Foo\BarBundle\EventListener\ArticleTagRemovalListener
    tags:
      - { name: doctrine_mongodb.odm.event_listener, event: preRemove }

Next in the custom repository class of your Article add the following method:

接下来,在文章的自定义存储库类中添加以下方法:

public function removeTag($tag)
{
    return $this
        ->createQueryBuilder()
        ->update()
        ->field('tags')->pull($tag)
        ->multiple(true)
        ->getQuery()
        ->execute();
}

This will remove the tag from all available articles before deleting it. If you want to cascade the delete operation to all article documents. (Thus, remove all articles with a particular tag when that tag is removed, use the following repository method.)

这将删除所有可用文章中的标记,然后再删除它。如果要将删除操作级联到所有文章文档。 (因此,删除该标记时删除具有特定标记的所有文章,请使用以下存储库方法。)

public function purgeByTag($tag)
{
    $result = $this
        ->createQueryBuilder()
        ->remove()
        ->field('tags')->equals($tag)
        ->getQuery()
        ->execute();

    return $result['n'];
}

Update the ArticleTagRemovalListener to call this method and done!

更新ArticleTagRemovalListener以调用此方法并完成!

#2


0  

By default Doctrine will not cascade any UnitOfWork operations to referenced documents so if wish to have this functionality you must explicitly enable it

默认情况下,Doctrine不会将任何UnitOfWork操作级联到引用的文档,因此如果希望具有此功能,则必须明确启用它

You can enable it on any field with either 'remove' or 'detach' depending on the behavior you want.

您可以使用“删除”或“分离”在任何字段上启用它,具体取决于您想要的行为。

@ReferenceOne(targetDocument="Profile", cascade={"detach"})

http://www.doctrine-project.org/docs/mongodb_odm/1.0/en/reference/reference-mapping.html#cascading-operations

#1


1  

I assume you have two collections, ArticleTag and Article in which articles have references to article tags. If you want to delete tag references from articles when a tag is removed you can implement an event listener.

我假设您有两个集合,ArticleTag和Article,其中的文章引用了文章标签。如果要在删除标记时从文章中删除标记引用,则可以实现事件侦听器。

Create a class:

创建一个类:

namespace Foo\BarBundle\EventListener;

use Doctrine\ODM\MongoDB\Event\LifecycleEventArgs;
use Foo\BarBundle\Document\Article;

class ArticleTagRemovalListener
{
    public function preRemove(LifecycleEventArgs $args)
    {
        $document = $args->getDocument();

        if ($document instanceof Article) {
            // Remove tag from all articles
            $args
                ->getDocumentManager()
                ->getRepository('FooBarBundle:Article')
                ->removeTag($document);
        }
    }
}

And register this class in your services.yml or xml file:

并在services.yml或xml文件中注册此类:

foo_bar.listener.tag_removal:
    class: Foo\BarBundle\EventListener\ArticleTagRemovalListener
    tags:
      - { name: doctrine_mongodb.odm.event_listener, event: preRemove }

Next in the custom repository class of your Article add the following method:

接下来,在文章的自定义存储库类中添加以下方法:

public function removeTag($tag)
{
    return $this
        ->createQueryBuilder()
        ->update()
        ->field('tags')->pull($tag)
        ->multiple(true)
        ->getQuery()
        ->execute();
}

This will remove the tag from all available articles before deleting it. If you want to cascade the delete operation to all article documents. (Thus, remove all articles with a particular tag when that tag is removed, use the following repository method.)

这将删除所有可用文章中的标记,然后再删除它。如果要将删除操作级联到所有文章文档。 (因此,删除该标记时删除具有特定标记的所有文章,请使用以下存储库方法。)

public function purgeByTag($tag)
{
    $result = $this
        ->createQueryBuilder()
        ->remove()
        ->field('tags')->equals($tag)
        ->getQuery()
        ->execute();

    return $result['n'];
}

Update the ArticleTagRemovalListener to call this method and done!

更新ArticleTagRemovalListener以调用此方法并完成!

#2


0  

By default Doctrine will not cascade any UnitOfWork operations to referenced documents so if wish to have this functionality you must explicitly enable it

默认情况下,Doctrine不会将任何UnitOfWork操作级联到引用的文档,因此如果希望具有此功能,则必须明确启用它

You can enable it on any field with either 'remove' or 'detach' depending on the behavior you want.

您可以使用“删除”或“分离”在任何字段上启用它,具体取决于您想要的行为。

@ReferenceOne(targetDocument="Profile", cascade={"detach"})

http://www.doctrine-project.org/docs/mongodb_odm/1.0/en/reference/reference-mapping.html#cascading-operations