mongoose Moongoose aggregate $match与id不匹配

3zwtqj6y  于 12个月前  发布在  Go
关注(0)|答案(6)|浏览(126)

我想通过ID(56e641d4864e5b780bb992c656e65504a323ee0812e511f2)显示产品,并显示折扣后的价格,如果可用。
我可以用aggregate来计算最终的价格,但是这会返回集合中的所有文档,如何让它只返回匹配的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)
        }
    })

x7rlezfr

x7rlezfr1#

您的ids变量将由“字符串”而不是ObjectId值构成。
Mongoose在常规查询中将ObjectId的字符串值“自动转换”为正确的类型,但这个does not happen in the aggregation pipeline,如issue #1399中所述。
相反,您必须手动执行正确的类型转换:

ids = ids.map(function(el) { return mongoose.Types.ObjectId(el) })

字符串
然后,您可以在管道阶段使用它们:

{ "$match": { "_id": { "$in": ids } } }


原因是因为聚合管道“通常”会改变文档结构,因此mongoose不会假定“模式”适用于任何给定管道阶段的文档。
这是可以理解的,“第一个”流水线阶段(当它是$match阶段时)应该这样做,因为文档确实没有被修改。
任何可能是“字符串”或至少不是正确的BSON类型的值都需要手动转换以进行匹配。

y0u0uwnf

y0u0uwnf2#

1.在mongoose中,它可以很好地使用find({_id:'606 c1 ceb 362 b366 a841171 dc'})
1.但是在使用聚合函数时,我们必须使用mongoose对象将_id转换为对象eg。
$match:{“_id”:mongoose.Types.ObjectId(“606c1ceb362b366a841171dc”)}
这会很好。

hs1rzwqc

hs1rzwqc3#

您可以简单地将您的id转换为

let id = mongoose.Types.ObjectId(req.query.id);

字符串
然后匹配

{ $match: { _id: id } },

jw5wzhpr

jw5wzhpr4#

而不是:

$match: { _id: "6230415bf48824667a417d56" }

字符串
用途:

$match: { _id: ObjectId("6230415bf48824667a417d56") }

z6psavjg

z6psavjg5#

使用此

$match: { $in : [ {_id: mongoose.Types.ObjectId("56e641d4864e5b780bb992c6 ")}, {_id: mongoose.Types.ObjectId("56e65504a323ee0812e511f2")}] }

字符串
因为Mongoose在常规查询中会自动将ObjectId的字符串值转换为正确的类型,但在聚合管道中不会发生这种情况。所以我们需要在管道查询中定义ObjectId转换。

8ftvxx2r

8ftvxx2r6#

使用mongoose 8+和typescript,我使用

let newId = new mongoose.mongo.ObjectId(id);

字符串
然后比赛阶段看起来像这样

"$match" : {
    "_id" : newId
}

相关问题