具有唯一密钥的Doctrine ODM flush()


Doctrine ODM flush() with unique key

我使用条令ODM来处理MongoDB。我有一些文件要保存,这些文件可能会不时重复。我只需要每个事件的一个副本,所以我使用散列的uniq键来确保事件只有1。

所以我做了几个->persistent($document);当我这样做的时候->flush();

我遇到了一个例外:localhost:27017:E11000重复密钥错误索引:dbname.event.$eventKey_1重复密钥:{:"keyValue"}

而且所有的数据从未持久化到MongoDB。所以问题是:是否有任何方法可以持久化uniq数据并忽略现有数据而不进行操作:

try {
    ->persist();
    ->flush();
} catch ('Exception $e) {}

对于每个文档?

谢谢。

更新:谢谢你的回答和时间,但我找到了确切的解决方案:)

Mongo函数插入有一个选项"ordered:"https://docs.mongodb.org/manual/reference/method/db.collection.insert/其允许即使在出现错误之后也继续插入。

教义使用Pecl扩展mongo。条令flush()使用此方法:http://www.php.net/manual/en/mongocollection.batchinsert.php具有选项"continueError"

所以如果你这样做:

$documentManager->flush(null, ['continueOnError' => true]);

它将保存所有没有错误的文档,并跳过所有有错误的文档。尽管它会抛出"''MongoDuplicateKeyException"。因此,您所需要的就是捕获此异常并处理或忽略它(取决于您的需要)。

如下所示:)

原生Doctrine方法不支持过滤唯一值-您需要自己完成。要在没有任何错误的情况下插入这些数据,您必须根据您的实体结构做一些事情:

  1. 使用您拥有的唯一密钥查找所有现有实体

  2. 查找在试图持久化的实体之间重复的唯一密钥

  3. 用您找到的实体替换现有实体

  4. 持久并刷新

如果没有至少一个额外的查询,就绝对没有机会做到这一点。如果您拥有现有实体的主键,则可以使用这些主键来获取引用对象。但不幸的是,根据条令文件,没有人支持通过唯一密钥获得参考:

http://doctrine-orm.readthedocs.org/en/latest/reference/limitations-and-known-issues.html#join-具有非主键的列

不能使用指向非主键的联接列。Doctrine会认为这些是主键,并使用数据创建懒惰加载代理,这可能会导致意想不到的结果。由于性能原因,条令不能在运行时验证此设置的正确性,只能通过validate Schema命令进行验证。

我无法使['continueOnError' => true]工作,因此以不同的方式解决:

$collection = $documentManager->getDocumentCollection(Content::class);
try {
    $collection->insertMany($arrayData, ['ordered' => false]);
} catch (BulkWriteException $exception) {
    // ignore duplicate key errors
    if (false === strpos($exception->getMessage(), 'E11000 duplicate key error')) {
        throw $exception;
    }
}

您只需执行以下操作:搜索现有id,编辑并保存。。

  • 使用条令+符号:

    $Document = $EntityManager->getRepository("ExpBundle:Document")->find(123);
    $Document->setTitile("Doc");  
    $EntityManager->flush();
    
  • 使用条令

    $Document = $EntityManager->find('Document', 1234);  
    $Document->setTitle("edited");  
    $EntityManager->flush();