MongoDB聚合中$_id传参类型不匹配导致查询为空求助
解决MongoDB聚合中自定义函数接收$_id为字符串而非ObjectId的问题
你碰到的这个问题其实是MongoDB聚合管道里一个容易踩的小坑:当你在聚合阶段(比如$addFields)里引用$_id并传给自定义函数时,它会被自动转换成字符串类型,而你函数里用这个字符串去匹配financial.successpayrequests集合的userID字段(应该是ObjectId类型),类型不匹配自然查不到任何结果。而硬编码传入ObjectId()时,参数本身就是正确的类型,所以能正常返回数据。
这里有两个简单的解决方案,你可以根据情况选择:
方案一:在自定义函数内部转换类型
最直接的方式就是在fetchUserCreadit函数里,把传入的字符串参数转为ObjectId类型,这样就能和userID的类型匹配上了。修改后的函数代码如下:
const fetchUserCreadit = function(uid) { // 将传入的字符串uid转为ObjectId类型 const userObjectId = ObjectId(uid); const succPays = db.financial.successpayrequests.aggregate([ { $match: { userID: userObjectId } }, { $group: { _id: null, amountSum: { $sum: '$amount' } } } ]).toArray(); return succPays; };
修改后,你原来的聚合查询就可以正常工作了:
db.getCollection('general.users').aggregate([ { $match: { _id: ObjectId("5a48894e4639fa6d7703c4f4") } }, { $addFields: { creadit: fetchUserCreadit("$_id") } } ])
方案二:在聚合管道中先转换$_id类型(MongoDB 4.0+适用)
如果你更倾向于在聚合管道里提前处理类型,可以用$toObjectId操作符把$_id转为ObjectId后再传入函数:
db.getCollection('general.users').aggregate([ { $match: { _id: ObjectId("5a48894e4639fa6d7703c4f4") } }, // 先把字符串类型的$_id转为ObjectId { $addFields: { userIdObj: { $toObjectId: "$_id" } } }, // 传入转换后的ObjectId { $addFields: { creadit: fetchUserCreadit("$userIdObj") } } ])
这个方案需要你的MongoDB版本在4.0及以上,因为$toObjectId是4.0才引入的操作符。
总的来说,方案一的适用性更广,不管MongoDB版本如何都能生效,而且逻辑更集中在函数内部,维护起来也更方便。
内容的提问来源于stack exchange,提问作者sadegh
相关产品推荐
相关产品推荐

