Model.aggregate 给了我与 mongo 控制台不同的结果(none for mongoose)
Model.aggregate gives me different results as in the mongo console (none for mongoose)
当我在控制台中执行以下命令时,我得到一个 nameID 和一个 min max。
db.prices.aggregate([
{"$match":{ nameID: { '$in': [ ObjectId('longid') ] } } }//replaced the actual value with longid
,{"$group":{"_id":"$nameID","nameID":{"$first": "$nameID"} ,"min":{"$min":"$price"},"max":{"$max":"$price"}}}
,{"$sort":{"min":1}}
,{"$limit":5}
])
在猫鼬中我得到一个空数组:
Price.aggregate([
{"$match":{ nameID: { '$in': [ 'longid' ] } }}//replaced the actual value with longid
,{"$group":{"_id":"$nameID","nameID":{"$first": "$nameID"} ,"min":{"$min":"$price"},"max":{"$max":"$price"}}}
,{"$sort":{"min":1}}
,{"$limit":5}
],function(){}//needs a callback passed or no promise is returned
).then(function(res){
console.log('got a totals:',res);//res is [] here
return Price.find({ nameID: { '$in': [ 'longid' ] } }}).exec();
}).then(function(res){
console.log(res.length);//yes, got 3 records
console.log(res[0]['price']);//yes, the price
对查询执行 Price.find 得到 3 条记录。
我是不是遗漏了什么或者这是 mongoose 的一个已知问题?
[更新]
对于聚合,我无法将 id 作为字符串传递,因此转换为 ObjectId 并且它起作用了。这是一个示例:
Price.aggregate([
{"$match":{ nameID: { '$in': [
new mongoose.Types.ObjectId('longid')//replaced the actual value with longid
]
}
}}
...
糟糕。从你的最后一条评论到我的最后一条评论,你已经强调了这里的问题。在大多数情况下,Mongoose 会根据应用的模式 "inspect" 和转换 "types" 到模型进行操作。它不能并且 "will not" 在聚合管道中执行此操作。所以你需要这样做:
var ObjectID = require("mongodb").ObjectID;
var actual_hex_string; // as received from input parameters
// then
Price.aggregate([
{"$match":{
"nameID": {
"$in": [ ObjectID(actual_hex_string) ]
}
}}
(...) // the rest of the pipeline
此外,$in
在这里似乎不合适,除非您打算在此处使用实际的 "array" 可能(并且已经转换)ObjectID
值。不要犯认为 "nameID" 是 "array" 的常见错误,因此您必须使用 $in
。 MongoDB 不关心这是一个数组还是单个值。 $in
用于同一字段的 $or
上下文中的 "multiple matches"。一个简单的相等匹配同样适用于文档中的 "array"。
当我在控制台中执行以下命令时,我得到一个 nameID 和一个 min max。
db.prices.aggregate([
{"$match":{ nameID: { '$in': [ ObjectId('longid') ] } } }//replaced the actual value with longid
,{"$group":{"_id":"$nameID","nameID":{"$first": "$nameID"} ,"min":{"$min":"$price"},"max":{"$max":"$price"}}}
,{"$sort":{"min":1}}
,{"$limit":5}
])
在猫鼬中我得到一个空数组:
Price.aggregate([
{"$match":{ nameID: { '$in': [ 'longid' ] } }}//replaced the actual value with longid
,{"$group":{"_id":"$nameID","nameID":{"$first": "$nameID"} ,"min":{"$min":"$price"},"max":{"$max":"$price"}}}
,{"$sort":{"min":1}}
,{"$limit":5}
],function(){}//needs a callback passed or no promise is returned
).then(function(res){
console.log('got a totals:',res);//res is [] here
return Price.find({ nameID: { '$in': [ 'longid' ] } }}).exec();
}).then(function(res){
console.log(res.length);//yes, got 3 records
console.log(res[0]['price']);//yes, the price
对查询执行 Price.find 得到 3 条记录。
我是不是遗漏了什么或者这是 mongoose 的一个已知问题?
[更新]
对于聚合,我无法将 id 作为字符串传递,因此转换为 ObjectId 并且它起作用了。这是一个示例:
Price.aggregate([
{"$match":{ nameID: { '$in': [
new mongoose.Types.ObjectId('longid')//replaced the actual value with longid
]
}
}}
...
糟糕。从你的最后一条评论到我的最后一条评论,你已经强调了这里的问题。在大多数情况下,Mongoose 会根据应用的模式 "inspect" 和转换 "types" 到模型进行操作。它不能并且 "will not" 在聚合管道中执行此操作。所以你需要这样做:
var ObjectID = require("mongodb").ObjectID;
var actual_hex_string; // as received from input parameters
// then
Price.aggregate([
{"$match":{
"nameID": {
"$in": [ ObjectID(actual_hex_string) ]
}
}}
(...) // the rest of the pipeline
此外,$in
在这里似乎不合适,除非您打算在此处使用实际的 "array" 可能(并且已经转换)ObjectID
值。不要犯认为 "nameID" 是 "array" 的常见错误,因此您必须使用 $in
。 MongoDB 不关心这是一个数组还是单个值。 $in
用于同一字段的 $or
上下文中的 "multiple matches"。一个简单的相等匹配同样适用于文档中的 "array"。