findOneAndUpdate 导致重复问题
findOneAndUpdate causing duplication problem
我在 mongoose 的 findOneAndUpdate 中遇到问题。
情况是我正在通过查找来更新文档。
查询如下:
UserModel.findOneAndUpdate({
individualId: 'some id'
}, {
$push: {
supporterOf: 'some string'
}
})
'supporterOf'是UserModel的ref,类型是'ObjectId'。
The issue i am facing here is that, 'some string' is being pushed twice under 'supporterOf' in the document.
谁能告诉我如何将数组元素压入文档中?
我最近遇到了同样的问题。但是,我设法通过其他一些逻辑(下面给出了详细信息)克服了这个问题,但无法理解为什么 findOneAndUpdate 插入 duplicate 背后的原因mongodb 中的条目。
您可以按照以下逻辑解决此问题。
使用 findOne 或 findById 而不是 findOneAndUpdate 在您的 collection 然后手动更新您的文档和 运行 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)
});
});
这不会插入重复项。但是,如果您知道重复背后的原因,必须更新此线程。
我遇到了同样的问题,解决方法是。
我一直在等待下面。
**await** schema.findOneAndUpdate(queryParms, {
"$push": {
"array1": arrayDetails,
"array2": array2Details
}
}, {
"upsert": true,
"new": true
},
function (error, updateResponse) {
if (error) {
throw new Error (error);
} else {
// do something with updateResponse;
}
});
简单地删除 await 帮助我解决了这个问题。
需要找到根本原因。
欢迎任何参考指针。
我遇到了同样的问题。我的代码是:
const doc = await model.findOneAndUpdate(
{filter}, {update},
{new: true}, (err, item) => if(err) console.log(err) }
)
res.locals.doc = doc
next();
问题是,由于某种原因,"new" 选项之后的回调创建了一个复式条目。我删除了回调,它起作用了。
我遇到了同样的问题。
我找到了适合我的解决方案:
我同时使用了回调和承诺(因此使用关键字“await”)。
Using a callback and a promise simultaneously will result in the query being executed twice. You should be using one or the other, but not both.
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();
UserModel.findOneAndUpdate(
{ _id: id },
{ object }
)
即使您使用 _id 作为参数,也不要忘记通过 id 明确过滤器
已接受答案的问题在于,当 findOneAndUpdate() 方法已经 returns 一个承诺时,它只能通过将其包装在一个不必要的额外承诺中来解决问题。此外,它同时使用了 promises 和 callbacks,这是你几乎不应该做的事情。
相反,我会采用以下方法:
为了可读性和 re-usability,我通常喜欢将我的更新查询逻辑与其他问题分开。所以我会做一个类似这样的包装函数:
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)
}
}
无需创建不必要的承诺,没有回调地狱,没有重复请求,更严格地遵守单一责任原则。
问题似乎源于组合等待和回调。我遇到了同样的问题,直到我意识到我正在使用 (err, resp) 回调 and a .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(...) 行后问题就解决了。
来自猫鼬文档:
- "Mongoose 查询不是 promises。为了方便起见,它们有一个用于 co 和 async/await 的 .then() 函数。但是,与 promises 不同的是,调用查询的 .then() 可以多次执行查询”
(https://mongoosejs.com/docs/queries.html#queries-are-not-promises)
就我而言,更改 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();
用$addToSet代替$push,应该可以解决问题。我认为创建猫鼬 'Model' 时使用的数据结构存在问题。我们知道 push 是一个数组(允许重复)操作,而 addToSet 可能是一个 Set 操作(Sets 不允许重复)。
$addToSet 而不是 $push 让我可以像这样防止在用户文档的 mongoDb 数组字段中重复输入。
const blockUserServiceFunc = async(req, res) => {
let filter = {
_id : req.body.userId
}
let update = { $addToSet: { blockedUserIds: req.body.blockUserId } };
await User.findOneAndUpdate(filter, update, (err, user) => {
if (err) {
res.json({
status: 501,
success: false,
message: messages.FAILURE.SWW
});
} else {
res.json({
status: 200,
success: true,
message: messages.SUCCESS.USER.BLOCKED,
data: {
'id': user._id,
'firstName': user.firstName,
'lastName': user.lastName,
'email': user.email,
'isActive': user.isActive,
'isDeleted': user.isDeleted,
'deletedAt': user.deletedAt,
'mobileNo': user.mobileNo,
'userName': user.userName,
'dob': user.dob,
'role': user.role,
'reasonForDeleting': user.reasonForDeleting,
'blockedUserIds': user.blockedUserIds,
'accountType': user.accountType
}
});
}
}
).catch(err => {
res.json({
status: 500,
success: false,
message: err
});
});
}
我在 mongoose 的 findOneAndUpdate 中遇到问题。 情况是我正在通过查找来更新文档。 查询如下:
UserModel.findOneAndUpdate({
individualId: 'some id'
}, {
$push: {
supporterOf: 'some string'
}
})
'supporterOf'是UserModel的ref,类型是'ObjectId'。
The issue i am facing here is that, 'some string' is being pushed twice under 'supporterOf' in the document.
谁能告诉我如何将数组元素压入文档中?
我最近遇到了同样的问题。但是,我设法通过其他一些逻辑(下面给出了详细信息)克服了这个问题,但无法理解为什么 findOneAndUpdate 插入 duplicate 背后的原因mongodb 中的条目。
您可以按照以下逻辑解决此问题。
使用 findOne 或 findById 而不是 findOneAndUpdate 在您的 collection 然后手动更新您的文档和 运行 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)
});
});
这不会插入重复项。但是,如果您知道重复背后的原因,必须更新此线程。
我遇到了同样的问题,解决方法是。
我一直在等待下面。
**await** schema.findOneAndUpdate(queryParms, {
"$push": {
"array1": arrayDetails,
"array2": array2Details
}
}, {
"upsert": true,
"new": true
},
function (error, updateResponse) {
if (error) {
throw new Error (error);
} else {
// do something with updateResponse;
}
});
简单地删除 await 帮助我解决了这个问题。 需要找到根本原因。 欢迎任何参考指针。
我遇到了同样的问题。我的代码是:
const doc = await model.findOneAndUpdate(
{filter}, {update},
{new: true}, (err, item) => if(err) console.log(err) }
)
res.locals.doc = doc
next();
问题是,由于某种原因,"new" 选项之后的回调创建了一个复式条目。我删除了回调,它起作用了。
我遇到了同样的问题。 我找到了适合我的解决方案:
我同时使用了回调和承诺(因此使用关键字“await”)。
Using a callback and a promise simultaneously will result in the query being executed twice. You should be using one or the other, but not both.
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();
UserModel.findOneAndUpdate(
{ _id: id },
{ object }
)
即使您使用 _id 作为参数,也不要忘记通过 id 明确过滤器
已接受答案的问题在于,当 findOneAndUpdate() 方法已经 returns 一个承诺时,它只能通过将其包装在一个不必要的额外承诺中来解决问题。此外,它同时使用了 promises 和 callbacks,这是你几乎不应该做的事情。
相反,我会采用以下方法:
为了可读性和 re-usability,我通常喜欢将我的更新查询逻辑与其他问题分开。所以我会做一个类似这样的包装函数:
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)
}
}
无需创建不必要的承诺,没有回调地狱,没有重复请求,更严格地遵守单一责任原则。
问题似乎源于组合等待和回调。我遇到了同样的问题,直到我意识到我正在使用 (err, resp) 回调 and a .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(...) 行后问题就解决了。
来自猫鼬文档:
- "Mongoose 查询不是 promises。为了方便起见,它们有一个用于 co 和 async/await 的 .then() 函数。但是,与 promises 不同的是,调用查询的 .then() 可以多次执行查询” (https://mongoosejs.com/docs/queries.html#queries-are-not-promises)
就我而言,更改 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();
用$addToSet代替$push,应该可以解决问题。我认为创建猫鼬 'Model' 时使用的数据结构存在问题。我们知道 push 是一个数组(允许重复)操作,而 addToSet 可能是一个 Set 操作(Sets 不允许重复)。
$addToSet 而不是 $push 让我可以像这样防止在用户文档的 mongoDb 数组字段中重复输入。
const blockUserServiceFunc = async(req, res) => {
let filter = {
_id : req.body.userId
}
let update = { $addToSet: { blockedUserIds: req.body.blockUserId } };
await User.findOneAndUpdate(filter, update, (err, user) => {
if (err) {
res.json({
status: 501,
success: false,
message: messages.FAILURE.SWW
});
} else {
res.json({
status: 200,
success: true,
message: messages.SUCCESS.USER.BLOCKED,
data: {
'id': user._id,
'firstName': user.firstName,
'lastName': user.lastName,
'email': user.email,
'isActive': user.isActive,
'isDeleted': user.isDeleted,
'deletedAt': user.deletedAt,
'mobileNo': user.mobileNo,
'userName': user.userName,
'dob': user.dob,
'role': user.role,
'reasonForDeleting': user.reasonForDeleting,
'blockedUserIds': user.blockedUserIds,
'accountType': user.accountType
}
});
}
}
).catch(err => {
res.json({
status: 500,
success: false,
message: err
});
});
}