教义 ODM (mongodb) 合并不起作用


doctrine ODM (mongodb) merge doesn't work

我使用merge()没有任何运气。我正在做几乎完全记录的事情:

/* @var $detachedDocument MyDocumentClass */ 
$detachedDocument = unserialize($serializedDocument);
$document = $dm->merge($detachedDocument);
$document->setLastUpdated(new 'MongoDate());
$dm->persist($document);

但这种变化永远不会持续下去。我必须这样做:

$dm->createQueryBuilder('MyDocumentClass')
    ->findAndUpdate()
    ->field('lastUpdated')->set(new 'MongoDate())
    ->getQuery()
    ->execute();

merge()似乎很简单,所以我很困惑为什么它不能像我认为的那样工作。

在您的第一个代码示例中,merge()后跟 persist() 是多余的,并且您省略了 flush() ,这是实际写入数据库的唯一操作(除非您手动执行查询,如在第二个示例中所做的那样)。如果你在 UnitOfWork::doMerge() 中浏览代码,你会看到它将保留对象(如果它没有 ID)或按其 ID 获取文档。最终结果是merge()返回一个托管文档。持久化可确保在调用文档后对其进行管理(它本身不返回任何内容)。如果您戳UnitOfWork::doPersist(),您会发现将托管对象传递给该方法实际上是一个 NOOP。

尝试将persist()替换为 flush() 。请注意,如有必要,您可以刷新单个文档,但默认情况下$dm->flush()处理所有托管对象。

如果这仍然没有帮助,我会确认 lastUpdated 字段已在 ODM 中正确映射。您可以检查$dm->getClassMetadata('MyDocumentClass')的输出进行确认。如果它不是映射字段,UnitOfWork 将检测到文档中没有更改,并且不会有任何要刷新的内容。

顺便说一句:在第二个代码示例中,您在没有任何搜索条件的情况下执行findAndUpdate()(仅指定set())。通常,您将修改与类似 equals()(在您的情况下可能是 ID)之类的内容配对,以确保以原子方式修改并返回单个文档。