MongoDB聚合:如何筛选数组不含根文档_id的文档?
问题原因分析
你的两种查询方式失效,核心原因是MongoDB对数组字段的匹配逻辑和你预期的不一致:
$ne 条件的问题:
- 普通
$match查询中不能直接用$_id作为操作符的值,MongoDB会将"$_id"视为字符串字面量,而非文档自身的_id字段值。 - 针对数组字段使用
$ne时,只要数组中存在任意一个元素不满足匹配条件,整个文档就会被返回。你的示例文档中存在一个refId不等于根_id的元素,因此会被错误返回。
- 普通
$nin 条件的问题:
$nin的逻辑是"数组中存在至少一个元素不在指定列表内",而非"数组中所有元素都不在列表内"。你的目标文档里有一个refId不在你指定的ObjectId数组中,所以符合$nin的匹配条件,导致文档被返回。
正确实现方案
要筛选出applications.firstTimeInstalled数组中完全不存在refId等于根文档_id的文档,需要使用聚合表达式$expr来引用文档自身字段,并结合数组检查逻辑:
方案一:使用 $in + $not
{ $match: { $expr: { $not: { $in: ["$_id", "$applications.firstTimeInstalled.refId"] } } } }
逻辑:$in检查根文档的_id是否存在于applications.firstTimeInstalled.refId数组中,$not取反后,就会筛选出不存在匹配项的文档。
方案二:使用 $filter + $size
{ $match: { $expr: { $eq: [ { $size: { $filter: { input: "$applications.firstTimeInstalled", cond: { $eq: ["$$this.refId", "$_id"] } } } }, 0 ] } } }
逻辑:用$filter过滤出数组中refId等于根_id的元素,再用$size获取过滤后的数组长度。当长度为0时,说明数组中没有匹配的refId,符合筛选要求。
内容的提问来源于stack exchange,提问作者TheStranger
相关产品推荐
相关产品推荐

