MongoDB聚合中$match结合$lte使用字段变量失效问题求助
为啥你的MongoDB 3.4聚合$match用字段引用会失效?
嘿,这个问题我之前踩过坑,咱们一步步来捋清楚原因~
首先先看你写的聚合查询:
db.users.aggregate([ { $addFields: { age: { $subtract: [57, 20] }, age2: { $subtract: [67, 20] } } }, { $project: { age: 1, age2: 1 } }, { $match: { age: { $lte: "$age" } } } ])
核心问题:$match阶段的语法限制
在MongoDB 3.4里,$match阶段使用的是和普通find()一样的查询语法,这种语法里,操作符(比如$lte)的参数只能是字面量(数字、字符串、布尔值这些),不能直接引用当前文档的字段(也就是$age这种写法)。
当你写{ age: { $lte: "$age" } }时,MongoDB会把"$age"当成一个普通的字符串字面量,而不是去读取当前文档里的age字段值。你的age字段是数字类型(37),拿数字和字符串"$age"做$lte比较,自然不会有任何文档匹配,所以查询看起来“失效”了。
为啥换成数字就正常?
当你把"$age"换成具体数字(比如37),查询变成{ age: { $lte: 37 } },这就符合普通查询的语法了:MongoDB会把每个文档的age字段值和数字37做比较,刚好你的age就是37,所以所有文档都能匹配上,查询就正常运行了。
3.4版本怎么实现字段间的比较?
如果你的需求是做字段值之间的比较(哪怕是和自身比较),在3.4里得换个思路:先通过聚合表达式算出比较结果,再用$match过滤。比如可以用$addFields先生成一个布尔字段,再匹配这个字段:
db.users.aggregate([ { $addFields: { age: { $subtract: [57, 20] }, age2: { $subtract: [67, 20] }, // 用聚合表达式算出age <= age的结果,得到true isAgeValid: { $lte: ["$age", "$age"] } } }, // 匹配布尔值为true的文档 { $match: { isAgeValid: true } }, // 最后保留需要的字段 { $project: { age: 1, age2: 1 } } ])
要是你以后升级到MongoDB 3.6及以上,就可以用$expr直接在$match里写聚合表达式,不用额外加阶段了:
db.users.aggregate([ { $addFields: { age: { $subtract: [57, 20] }, age2: { $subtract: [67, 20] } } }, { $project: { age: 1, age2: 1 } }, { $match: { $expr: { $lte: ["$age", "$age"] } } } ])
内容的提问来源于stack exchange,提问作者xfankit
相关产品推荐
相关产品推荐

