Mongoose中的findOneAndUpdate和upsert出现重复键错误

9
我在使用findOneAndUpdate时遇到了一些问题,当来自我的csv文件的两个或多个行具有相同的电子邮件地址时,我会遇到问题。在我的模型中,电子邮件地址设置为唯一,并且我认为findOneAndUpdate将让我处理csv文件中的重复项。以下是代码。在这里阅读到,这是因为查询中的字段(在此情况下为电子邮件)也是我要在找不到记录的情况下创建的字段之一。我不确定这是否正确。无论如何,电子邮件是我的标识符,因此必须在其中。
更详细地解释一下行为:
  1. 当csv文件包含一个在运行脚本之前已存储在MongoDB中的电子邮件地址时,findOneAndUpdate完美地工作
  2. 然而,当我有两条记录在csv文件中共享相同的电子邮件地址,但在运行脚本之前没有存储此电子邮件地址的记录时,我有时会收到重复键错误,如下所示:{ MongoError: E11000 duplicate key error collection: db.accounts index: email_1 dup key: { : "xxxxx@yahoo.com" }
  3. 我在上面写了有时,因为有时(尽管较少),我不会得到错误,一切正常。
代码:
for (let i = 0; i < accounts.length; i++) {
   let query = {'email': accounts[i].email};
   let accountHolderDoc = {
       email: accounts[i].email,
       name: {
         first: accounts[i].accountHolderFName,
         last: accounts[i].accountHolderLName,
       },
    };

    promise = AccountHolder
        .findOneAndUpdate(
            query, {$set: accountHolderDoc}, {upsert: true, new: true})
        .then(function(accountHolder) { ... })
        .catch( ... );
   ...
}
1个回答

3

这篇文章表明查找和保存不存在的文档不是原子操作,这意味着在查找和保存之间,另一个查询可能会为相同的搜索条件产生未找到的结果。那么唯一的解决方案似乎是确保处理重复键错误,例如通过重新应用 MongoDB 操作到被抛弃的文档。


我建议您使用async.js进行循环,特别是使用async.eachSeries()一次执行一个操作。将同步的for与异步的Mongoose操作混合使用通常会导致问题。 - Mikey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接