You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 22:14:08