Doctrine2:如何处理丢失的关系文档

时间:2015-04-07 13:35:01

标签: php mongodb symfony doctrine-orm

在一个巨大的数据集中,当删除一个文档时,我有时会出现不一致的情况。使用Doctrine ODM和FosREST的Symfony2应用程序

$a = new Element();
$b = new Element();
$c = new List();
$c->addElement($a);
$c->addElement($b);

$em->persist($c);

此时保存完美无缺

在99%的情况下,$ a和$ b仍然是有效的文件,以后加载$ c。 有时会删除$ a或$ b而不更新$ c中的引用。

- >此时$ c的下一次加载将失败并出现\ Doctrine \ ODM \ MongoDB \ DocumentNotFoundException

(消息类似于:" MongoDBODMProxies__CG __ \ App \ Model \ Element"文档带有标识符" 541417702798711d2900607c"找不到。


现在处理这种情况的最佳方法是什么?

我在考虑

  • 捕获异常并检查它尝试加载的引用是否在元素模型
  • fosRest中的自定义异常处理程序,用于检查
  • 映射中的自定义存储库功能,并检查一切是否仍然有效(+以某种方式存储缺少元素) - >但这会迫使我每次都检查一下"错误"已设置

更新:文档之间的映射比我在此处描述的要复杂一些

  • 一个元素基本上是一个由鉴别器分隔的集合,其中只有一种类型的字段引用另一个文档(我称之为#34; Tree"现在)
  • 树可用于数千个ElementTree(包含树的特定类型)
  • 有时可以删除Tree(这已经是一个运行缓慢的过程,因为当时需要更新大量数据)
  • 我现在需要找出需要更改的列表,并基本上拒绝对这些列表的api调用以及特定元素不再可用的信息。

2 个答案:

答案 0 :(得分:1)

要检查MongoDB的一些事项:

  1. 确保没有循环引用(例如,如果类List上有属性$ elements,并且引用设置为true,请确保在Elements类中未引用List)和你的映射是一致的。

  2. 在addElement函数中,如果引用保存在Element类上,请确保在函数内部也调用$ element-> setList($ this)。 (对于removeElement也一样,如果需要,取消设置引用)

  3. 确保您级联所有必要的操作。 (例如级联:[“持久”,“删除”,“刷新”或“全部”]

  4. 您可以使用

    检查映射
    $ app/console doctrine:mongodb:mapping:info  
    
    1. 最后,如果您希望删除该文档,但是从代理对象收到错误,则可以清除元数据缓存

      $ app/console doctrine:mongodb:cache:clear-metadata  
      

答案 1 :(得分:1)

目前无效的解决方案

我现在选择抛出一个新的Exception(重要的是不要让doctrine抛出一个,因为它会拒绝同一个请求中的任何持久尝试)。

在PostLoad LifecycleEvent中,我现在检查以下内容(简化):

if ($document instanceof List) {
  foreach ($document->getElements() as $element) {
    // at this moment $element->getId() is already defined but not yet loaded from mongo
    $result = $this->elementRepository->findBy(array(‘_id’ => $element->getId()));
    if (sizeof($result)==0) {
      throw new InvalidElementInList($element->getId());
    }
  }
}
在RestController中,这使我能够捕获这个特定的异常,并从列表中删除无效元素+,向用户返回一个自定义视图,表明该元素已被删除。