Node.js中MongoDB嵌套数组过滤:保留顶层文档并筛选指定用户最新评论
解决MongoDB嵌套数组过滤+取最新元素的需求
嘿,我明白你的需求了——要保留所有顶层文档,但只保留comments数组里emp为"007"的最新评论。你之前用$slice只能取最后一条,但没法先过滤特定emp的评论,这确实得用聚合管道来实现,因为普通的find().project没法组合过滤和切片这两个操作。
下面给你两种可行的方案,按需选择:
方案一:基础版(过滤后直接取最新)
这个方法先过滤出emp="007"的评论,再取过滤后的数组最后一个元素(也就是最新的那条):
await db.collection('status').aggregate([ { $addFields: { comments: { // 先过滤出emp为007的评论,再取最后一条 $slice: [ { $filter: { input: "$comments", as: "commentItem", cond: { $eq: ["$$commentItem.emp", "007"] } } }, -1 ] } } } ]).toArray();
效果说明:
- 对于
machine=1的文档,过滤后comments数组只剩emp="007"的那条评论 - 对于
machine=2的文档,因为没有emp="007"的评论,comments会变成空数组
方案二:进阶版(空结果时自定义处理)
如果希望没有符合条件的评论时,把comments设为null或者直接移除,可以用$cond做判断:
await db.collection('status').aggregate([ { $addFields: { comments: { $let: { vars: { filtered: { $filter: { input: "$comments", as: "commentItem", cond: { $eq: ["$$commentItem.emp", "007"] } } } }, in: { $cond: { if: { $gt: [{ $size: "$$filtered" }, 0] }, then: { $slice: ["$$filtered", -1] }, else: null // 这里可以换成[]或者用$$REMOVE直接删除字段 } } } } } } ]).toArray();
为什么不用find().project?
因为$slice只能对原数组进行切片,无法先执行过滤操作。聚合管道的优势在于可以把多个数组操作(过滤、切片、判断)组合起来,完美匹配你的需求。
内容的提问来源于stack exchange,提问作者Nathan Field
相关产品推荐
相关产品推荐

