如果字段';MongoDB&;中的s值达到0;Node.js
我有像购物清单这样的对象数组。例如,我在列表中添加了2个产品如果字段';MongoDB&;中的s值达到0;Node.js,node.js,mongodb,mongodb-query,aggregation-framework,Node.js,Mongodb,Mongodb Query,Aggregation Framework,我有像购物清单这样的对象数组。例如,我在列表中添加了2个产品 cart:[{id:1,quantity:15},{id:2,quantity:5}] 我可以很好地增加和减少数量,但我想做的是,当我减少到0时,我希望它显示为我的购物车中没有,我知道这可能是拉,我尝试了这个,但失败了。idk我做错了什么,当我尝试console.log(用户)时,它给我空值,因为它没有看到“cart.quantity”:0,idk为什么不。用户信息和布局是好的 router.get("/:productId/de
cart:[{id:1,quantity:15},{id:2,quantity:5}]
我可以很好地增加和减少数量,但我想做的是,当我减少到0时,我希望它显示为我的购物车中没有,我知道这可能是拉,我尝试了这个,但失败了。idk我做错了什么,当我尝试console.log(用户)时,它给我空值,因为它没有看到“cart.quantity”:0,idk为什么不。用户信息和布局是好的
router.get("/:productId/decrement", auth, async (req, res) => {
const user = await User.findOne({
id: req.user._id,
"cart.quantity": 0,
});
if (user) {
await User.findOneAndUpdate(
{
id: req.user._id,
"cart.id": req.params.productId,
"cart.quantity": 0,
},
{ $pull: { cart: { id: req.params.productId } } }
);
} else {
await User.findOneAndUpdate(
{
id: req.user._id,
"cart.id": req.params.productId,
},
{ $inc: { "cart.$.quantity": -1 } },
{ new: true },
(err, doc) => {
if (err) {
return res.json({ success: false, err });
}
return res.json({ success: true, cart: doc });
}
);
}
});
这是我的用户模型
const userSchema = mongoose.Schema({
name: {
type: String,
maxlength: 50,
},
email: {
type: String,
trim: true,
unique: 1,
},
password: {
type: String,
minglength: 5,
},
lastname: {
type: String,
maxlength: 50,
},
cart: { type: Array, default: [] },
在MongoDB版本>=3.2:
router.get("/:productId/decrement", auth, async (req, res) => {
try {
let bulkArr = [
{
updateOne: {
filter: {
id: req.user._id,
"cart.id": req.params.productId,
"cart.quantity": 1, // You can use {$lte : 1}
},
update: { $pull: { 'cart': { id: req.params.productId } } },
},
},
{
updateOne: {
filter: {
id: req.user._id,
"cart.id": req.params.productId
},
update: { $inc: { "cart.$.quantity": -1 } },
},
},
];
await User.bulkWrite(bulkArr);
return res.json({ success: true });
} catch (error) {
console.log("Error ::", error);
return res.json({ success: false, ...{error} });
}
});
注意:
router.get("/:productId/decrement", auth, async (req, res) => {
try {
let bulkArr = [
{
updateOne: {
filter: {
id: req.user._id,
"cart.id": req.params.productId,
"cart.quantity": 1, // You can use {$lte : 1}
},
update: { $pull: { 'cart': { id: req.params.productId } } },
},
},
{
updateOne: {
filter: {
id: req.user._id,
"cart.id": req.params.productId
},
update: { $inc: { "cart.$.quantity": -1 } },
},
},
];
await User.bulkWrite(bulkArr);
return res.json({ success: true });
} catch (error) {
console.log("Error ::", error);
return res.json({ success: false, ...{error} });
}
});
异步等待
的&回调()
。请尽量避免bulkWrite
中,将执行所有筛选条件,但仅当相应的筛选匹配(单个操作的种类)但在一个DB调用中时,才会执行更新操作bulkWrite
输出“写入结果”,但如果需要结果文档,则需要执行.find()
调用。但由于使用bulkWrite
的全部目的是避免多次调用数据库-如果结果没有错误,您可以向前端发送成功消息,然后它们可以显示适当的计数(通过执行递减)在MongoDB版本>=4.2:
router.get("/:productId/decrement", auth, async (req, res) => {
try {
let bulkArr = [
{
updateOne: {
filter: {
id: req.user._id,
"cart.id": req.params.productId,
"cart.quantity": 1, // You can use {$lte : 1}
},
update: { $pull: { 'cart': { id: req.params.productId } } },
},
},
{
updateOne: {
filter: {
id: req.user._id,
"cart.id": req.params.productId
},
update: { $inc: { "cart.$.quantity": -1 } },
},
},
];
await User.bulkWrite(bulkArr);
return res.json({ success: true });
} catch (error) {
console.log("Error ::", error);
return res.json({ success: false, ...{error} });
}
});
由于我们可以在更新中使用聚合,您可以执行以下操作:
User.findOneAndUpdate({id: req.user._id, 'cart.id': req.params.productId},
[
{
$addFields: {
cart: {
$reduce: {
input: "$cart",
initialValue: [],
in: {
$cond: [
{ $and: [ { $eq: [ "$$this.id", req.params.productId ] }, { $gt: [ "$$this.quantity", 1 ] } ] }, // condition
{
$concatArrays: [ "$$value", [ { $mergeObjects: [ "$$this", { quantity: { $add: [ "$$this.quantity", -1 ] } } ] } ]]
}, // condition is true, So we're decrementing & pushing object to accumulator array
{
$cond: [ { $eq: [ "$$this.id", req.params.productId ] }, "$$value", { $concatArrays: [ "$$value", [ "$$this" ] ] } ]
} // condition failed, so pushing objects where id != input productId
]
}
}
}
}
}
], {new: true})
参考:
此处的测试聚合管道:
注意:
router.get("/:productId/decrement", auth, async (req, res) => {
try {
let bulkArr = [
{
updateOne: {
filter: {
id: req.user._id,
"cart.id": req.params.productId,
"cart.quantity": 1, // You can use {$lte : 1}
},
update: { $pull: { 'cart': { id: req.params.productId } } },
},
},
{
updateOne: {
filter: {
id: req.user._id,
"cart.id": req.params.productId
},
update: { $inc: { "cart.$.quantity": -1 } },
},
},
];
await User.bulkWrite(bulkArr);
return res.json({ success: true });
} catch (error) {
console.log("Error ::", error);
return res.json({ success: false, ...{error} });
}
});
很少有MongoDB客户端会抛出一个错误,说“更新操作可能只包含原子运算符”,这种情况下您可以使用
.update()
或者使用代码测试它,因为大多数支持4.2
的驱动程序都不会抛出这样的错误。您的MongoDB版本是什么?我的版本是5.4.20MongoDB版本4.2.x
目前是最新版本!我猜这是您的驱动程序版本(如果我没记错的话,您可能正在使用mongoose)(驱动程序帮助将编程语言代码连接到数据库),我在询问MongoDB服务器版本。。您可以通过执行db.version()
来获得它。是的,您是对的,它的mongoose,我通过npm下载了mongoose,但没有对mongodb做任何操作,只是使用网站上的应用程序代码来连接。我也应该安装吗?当你说网站是mongo atlas吗?如果是,那么当您登录到门户网站时,您可以看到MongoDB服务器版本,或者至少您可以在robo3T或shell(一旦连接到DB)中发出上述命令,以了解您正在使用的版本。谢谢您,我尝试了4.2,它工作得很好,但我仍然不知道为什么我的版本没有,尤其是User.findOne({id:req.User.\u id,“cart.quantity”: 0, });@托利马:不确定,id:req.user.\u id
是否唯一?另外,您确定当您使用查询时,集合中是否存在任何匹配的单据?是的,它是唯一的,它给我空值,我希望它在我减量到之后匹配0@Tolima:尝试直接对数据库执行查询并检查结果,MongoDB文档中的id
字段的类型是什么?检查输入类型是否与文档中的字段类型匹配(如果类型不匹配,通常不会得到任何文档,最终。findOne
将返回null
)当我发布增量请求时,查询工作正常,但我也注意到,当我减少或增加它时,它不是1乘1,这是另一个问题,您的代码也解决了它,所以我决定不关注我的旧代码,我必须了解$reduce部分,这似乎很难