Moongoose 聚合 $match 与 ID 不匹配 [英] Moongoose aggregate $match does not match id's

查看:34
本文介绍了Moongoose 聚合 $match 与 ID 不匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想按 id 显示产品(56e641d4864e5b780bb992c656e65504a323ee0812e511f2)并显示减去折扣后的价格(如果有).

I want to show products by ids (56e641d4864e5b780bb992c6 and 56e65504a323ee0812e511f2) and show price after subtracted by discount if available.

我可以使用聚合计算最终价格,但这会返回集合中的所有文档,如何使其仅返回匹配的 ID

I can count the final price using aggregate, but this return all document in a collection, how to make it return only the matches ids

"_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 查询,它返回空数组

and if i add this $in query, it returns empty array

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)
        }
    })

推荐答案

您的 ids 变量将由字符串"构成,而不是 ObjectId 值.

Your ids variable will be constructed of "strings", and not ObjectId values.

Mongoose 在常规查询中将 ObjectId 的字符串值自动转换"为正确的类型,但这 不会在聚合管道中发生,如问题 #1399 中所述.

Mongoose "autocasts" string values for ObjectId into their correct type in regular queries, but this does not happen in the aggregation pipeline, as in described in issue #1399.

相反,您必须进行正确的转换才能手动输入:

Instead you must do the correct casting to type manually:

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

然后你可以在你的管道阶段使用它们:

Then you can use them in your pipeline stage:

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

原因是因为聚合管道通常"会改变文档结构,因此猫鼬不会假设架构"适用于任何给定管道阶段的文档.

The reason is because aggregation pipelines "typically" alter the document structure, and therefore mongoose makes no presumption that the "schema" applies to the document in any given pipeline stage.

当它是 $match 阶段时,第一个"管道阶段应该这样做是有争议的,因为文档确实没有改变.但现在情况并非如此.

It is arguable that the "first" pipeline stage when it is a $match stage should do this, since indeed the document is not altered. But right now this is not how it happens.

任何可能是字符串"或至少不是正确 BSON 类型的值都需要手动转换才能匹配.

Any values that may possibly be "strings" or at least not the correct BSON type need to be manually cast in order to match.

这篇关于Moongoose 聚合 $match 与 ID 不匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆