findOneAndUpdate导致重复问题

时间:2019-03-11 13:51:10

标签: arrays node.js mongodb mongoose array-push

我在猫鼬的findOneAndUpdate中遇到问题。 情况是我正在通过查找来更新文档。 查询如下:

UserModel.findOneAndUpdate({
individualId: 'some id'
}, {
$push: {
supporterOf: 'some string'
}
})

'supporterOf'是UserModel的引用,其类型为'ObjectId'。

  

我在这里面临的问题是,“某些字符串”在文档的“ supporterOf”下被两次推送。

谁能告诉我如何在文档中推送数组元素?

9 个答案:

答案 0 :(得分:1)

我最近遇到了同样的问题。但是,我设法通过其他一些逻辑(以下详细信息)解决了这个问题,但是不明白为什么 findOneAndUpdate 在mongodb中插入 duplicate 条目的原因。

您可以通过遵循以下逻辑来克服此问题。

使用 findOne findById 代替 findOneAndUpdate 来搜索集合中的文档,然后手动更新文档并运行 save ()

您可以使用此代码段

更好地了解
return new Promise(function (resolve, reject) {
    Model.findOne({
            someCondition...
        }, function (err, item) {
            if (err) {
                reject(err);
            } else {
                item.someArray.push({
                    someKeyValue...
                });
                item.save().then((result) => {
                    resolve(result)
                }).catch((err) => {
                    reject(err)
                });
            }
        }).catch((err) => {
            reject(err)
        });
   });

这不会插入重复的项目。但是,如果您知道重复的原因,则必须更新此线程。

答案 1 :(得分:1)

我遇到了同样的问题,解决方案有点奇怪。

我一直在等待,如下所示。

 **await** schema.findOneAndUpdate(queryParms, {
                "$push": {
                    "array1": arrayDetails,
                    "array2": array2Details
                }
            }, {
                "upsert": true,
                "new": true
            },
            function (error, updateResponse) {
                if (error) {
                    //mongoDb.closeMongoCon(mongoose);
                    console.log('error ', error);
                    deferred.reject(data);
                } else {
                    console.log('updateResponse ', updateResponse);
                    deferred.resolve(updateResponse);
                }
            });

简单地删除等待状态有助于解决此问题。 需要找到根本原因。 欢迎任何参考指针。

答案 2 :(得分:1)

接受的答案的问题在于,当findOneAndUpdate()方法已经返回了一个Promise时,它只能通过将它包装在一个不必要的附加Promise中来解决问题。此外,它同时使用了Promise和回调,这是您几乎永远都不应做的事情。

相反,我将采用以下方法:

我通常希望将更新查询逻辑与其他方面分开,以保持可读性和可重用性。所以我将使包装函数类似于:

const update = (id, updateObj) => {
    const options = {
      new: true,
      upsert: true
    }
    return model.findOneAndUpdate({_id: id}, {...updateObj}, options).exec()
}

此功能可以在我的整个应用程序中重复使用,从而使我不必重写重复的选项设置或exec调用。

然后,我将拥有一些其他功能,负责调用查询,将值传递给查询并处理从查询返回的内容。

有点像

const makePush = async () => {
   try {
     const result = await update('someObjectId', {$push: {someField: value}});
     // do whatever you want to do with the updated document
   catch (e) {
     handleError(e)
    }
 }

无需创建不必要的承诺,无需回调地狱,无需重复的请求,并且可以更好地遵守单一职责原则。

答案 3 :(得分:0)

我遇到了同样的问题。我的代码是:

const doc = await model.findOneAndUpdate(
{filter}, {update},
{new: true}, (err, item) =>  if(err) console.log(err) }
)
res.locals.doc = doc
next();

问题是,由于某种原因,“ new”选项之后的此回调正在创建重复条目。我删除了回调并成功了。

答案 4 :(得分:0)

我有同样的问题。 我为我找到了解决方案:

我同时使用了回调和Promise(因此使用关键字“ await”)。

同时使用回调和Promise将导致查询执行两次。您应该使用其中一个,但不能同时使用。

  options = {
    upsert: true  // creates the object if it doesn't exist. defaults to false.
  };
  await Company.findByIdAndUpdate(company._id,
    { $push: { employees: savedEmployees } },
    options,
    (err) => {
       if (err) {
          debug(err);
       }
    }
  ).exec();

  options = {
    upsert: true  // creates the object if it doesn't exist. defaults to false.
  };
  await Company.findByIdAndUpdate(company._id,
    { $push: { employees: savedEmployees } },
    options
  ).exec();

答案 5 :(得分:0)

UserModel.findOneAndUpdate(
{ _id: id },
{ object }
)

即使您使用_id作为参数,也不要忘记通过id明确显示过滤器

答案 6 :(得分:0)

问题似乎源于等待和回调的结合。在我意识到我正在使用(err,resp)回调 .catch(...)之前,我遇到了同样的问题。

models[auxType].findOneAndUpdate(
    filter,
    updateObject,
    options,
    (err, resp)=>{
        if (err) {
            console.log("Update failed:",err)
            res.json(err)
        } else if (resp) {
            console.log("Update succeeded:",resp)
            res.json(resp)
        } else {
            console.log("No error or response returned by server")
        }
    })
    .catch((e)=>{console.log("Error saving Aux Edit:",e)}); // << THE PROBLEM WAS HERE!!

我删除.catch(...)行后,问题就解决了。

来自猫鼬的文档:

答案 7 :(得分:0)

就我而言,更改 async 回调解决了问题。

改变这个:

await schema.findOneAndUpdate(
    { queryData },
    { updateData },
    { upsert: true },
    (err) => {
      if (err) console.log(err); 
      else await asyncFunction();
    }
  );

为此:

await schema.findOneAndUpdate(
    { queryData },
    { updateData },
    { upsert: true },
    (err) => {
      if (err) console.log(err);
    }
  );
 if (success) await asyncFunction();

答案 8 :(得分:0)

用$addToSet代替$push,应该可以解决问题。我相信在创建猫鼬“模型”时使用的数据结构存在问题。我们知道 push 是一个数组(允许重复)操作,而 addToSet 可能是一个 Set 操作(集合不允许重复)。