MongoDB技术问询:投影层判断orderDetails.movieName是否存在
解决MongoDB聚合投影中判断数组元素字段是否存在的问题
你的问题核心是要在聚合投影层判断orderDetails数组中是否存在带有movieName字段的元素对吧?原来的查询只检查了数组第一个元素的movieName是否不为null,这会有两个明显的问题:一是如果数组里有多个元素,第一个没有movieName但后面的元素有,查询会误判为不存在;二是$ne判断null没法区分“字段不存在”和“字段存在但值为null”的情况。
这里给你两个靠谱的解决方案:
方案一:用$filter + $size判断
这个方法的思路是先筛选出数组中包含movieName字段的元素,再看筛选后的数组长度是否大于0:
db.BookingDetails.aggregate([ { $project: { OrderExists: { $cond: [ // 筛选出有movieName字段的元素,判断长度是否大于0 { $gt: [ { $size: { $filter: { input: "$orderDetails", cond: { $exists: ["$$this.movieName", true] } } } }, 0 ] }, 1, // 存在则返回1 0 // 不存在则返回0 ] } } } ])
如果你的需求是movieName不仅要存在,还不能是null,可以把$filter的条件改成:
cond: { $and: [ { $exists: ["$$this.movieName", true] }, { $ne: ["$$this.movieName", null] } ]}
方案二:用$map + $anyElementTrue判断
这个方法是先把数组每个元素转换成“是否包含movieName”的布尔值,再判断是否有至少一个true:
db.BookingDetails.aggregate([ { $project: { OrderExists: { $cond: [ // 把每个元素转成是否有movieName的布尔值,再判断是否有true { $anyElementTrue: { $map: { input: "$orderDetails", in: { $exists: ["$$this.movieName", true] } } } }, 1, 0 ] } } } ])
这个方案更直观,$map会生成一个布尔数组,比如第一个文档会生成[true],第二个空数组会生成[],$anyElementTrue对空数组返回false,刚好符合你的判断需求。
为什么原来的查询无效?
你原来用$orderDetails.0.movieName只能检查数组的第一个元素,没法覆盖数组中其他元素的情况;而且$ne: [xxx, null]没法区分“字段不存在”和“字段存在但值为null”,如果你的场景中有元素存在movieName但值为null的情况,也会被误判。
内容的提问来源于stack exchange,提问作者Nandy
相关产品推荐
相关产品推荐

