我希望按ID显示产品(56e641d4864e5b780bb992c6
和56e65504a323ee0812e511f2
),并在扣除可用折扣后显示价格。
我可以使用聚合来计算最终价格,但这会返回集合中的所有文档,如何使其仅返回匹配ID
"_id" : ObjectId("56e641d4864e5b780bb992c6"),
"title" : "Keyboard",
"discount" : NumberInt(10),
"price" : NumberInt(1000)
"_id" : ObjectId("56e65504a323ee0812e511f2"),
"title" : "Mouse",
"discount" : NumberInt(0),
"price" : NumberInt(1000)
"_id" : ObjectId("56d90714a48d2eb40cc601a5"),
"title" : "Speaker",
"discount" : NumberInt(10),
"price" : NumberInt(1000)
这是我的查询
productModel.aggregate([
{
$project: {
title : 1,
price: {
$cond: {
if: {$gt: ["$discount", 0]}, then: {$subtract: ["$price", {$divide: [{$multiply: ["$price", "$discount"]}, 100]}]}, else: "$price"
}
}
}
}
], function(err, docs){
if (err){
console.log(err)
}else{
console.log(docs)
}
})
如果我添加此$in
查询,则返回空数组
productModel.aggregate([
{
$match: {_id: {$in: ids}}
},
{
$project: {
title : 1,
price: {
$cond: {
if: {$gt: ["$discount", 0]}, then: {$subtract: ["$price", {$divide: [{$multiply: ["$price", "$discount"]}, 100]}]}, else: "$price"
}
}
}
}
], function(err, docs){
if (err){
console.log(err)
}else{
console.log(docs)
}
})
答案 0 :(得分:30)
您的ids
变量将由"字符串"而不是ObjectId
值构成。
Mongoose" autocasts" ObjectId
的字符串值在常规查询中的正确类型,但是does not happen in the aggregation pipeline,如问题#1399中所述。
相反,您必须执行正确的转换才能手动输入:
ids = ids.map(function(el) { return mongoose.Types.ObjectId(el) })
然后您可以在管道阶段使用它们:
{ "$match": { "_id": { "$in": ids } } }
原因是聚合管道"通常"改变文档结构,因此猫鼬没有假设"架构"适用于任何给定管道阶段的文档。
有争议的是"第一"管道阶段,当它是$match
阶段时,应该这样做,因为确实不会改变文档。但是现在这不是它发生的方式。
可能是"字符串"的任何值。或者至少不需要手动转换正确的BSON类型以便匹配。
答案 1 :(得分:2)
您可以简单地将您的 id 转换为
let id = mongoose.Types.ObjectId(req.query.id);
然后匹配
{ $match: { _id: id } },
答案 2 :(得分:1)
在 mongoose 中,它与 find({_id:'606c1ceb362b366a841171dc'}) 一起工作得很好
但是在使用聚合函数时,我们必须使用 mongoose 对象将 _id 转换为对象,例如。
$match: { "_id": mongoose.Types.ObjectId("606c1ceb362b366a841171dc") }
这会正常工作。