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

MongoDB聚合查询如何将嵌套二维数组合并为去重一维数组

MongoDB聚合:多数组字段ObjectId合并去重输出一维数组

问题原因

$addToSet针对数组字段做聚合时,会把每个文档的数组整体作为集合元素存入,最终得到二维嵌套数组,且无法自动处理三个字段之间的重复值,因此不符合预期。

正确聚合实现

以下管道兼容原有的$match、$facet、$group逻辑,单查询即可输出去重后的一维ObjectId数组:

db.funds.aggregate([
  // 原有匹配阶段保持不变
  {
    $match: {
      accountId: ObjectId("替换为实际accountId值"),
      projectId: ObjectId("替换为实际projectId值"),
      aps: "替换为实际aps匹配值"
    }
  },
  // 若原有逻辑包含$facet,保持$facet结构不变,在对应分支内追加后续处理即可
  // 示例$facet结构参考:
  // {
  //   $facet: {
  //     idList: [
  //       // 原有$group阶段
          {
            $group: {
              _id: null,
              personalIdRootList: { $addToSet: "$personalIdRoot" },
              personalIdFillList: { $addToSet: "$personalIdFill" },
              personalIdCapList: { $addToSet: "$personalIdCap" }
            }
          },
  //       // 新增数组打平+合并去重阶段
          {
            $project: {
              _id: 0,
              values: {
                $setUnion: [
                  // 打平personalIdRoot二维数组
                  {
                    $reduce: {
                      input: "$personalIdRootList",
                      initialValue: [],
                      in: { $concatArrays: ["$$value", "$$this"] }
                    }
                  },
                  // 打平personalIdFill二维数组
                  {
                    $reduce: {
                      input: "$personalIdFillList",
                      initialValue: [],
                      in: { $concatArrays: ["$$value", "$$this"] }
                    }
                  },
                  // 打平personalIdCap二维数组
                  {
                    $reduce: {
                      input: "$personalIdCapList",
                      initialValue: [],
                      in: { $concatArrays: ["$$value", "$$this"] }
                    }
                  }
                ]
              }
            }
          }
  //     ]
  //     // 其他facet统计分支保持原有逻辑不变
  //   }
  // }
])

逻辑说明

  • $reduce搭配$concatArrays:将$addToSet输出的每个二维数组逐层拼接,打平为一维数组
  • $setUnion:合并三个打平后的一维数组,自动过滤所有重复ObjectId(包括同字段内、跨字段的重复值),最终返回无重复的单层一维数组

性能优化方案

如果不需要保留$facet多分支统计,可将数组合并逻辑前置,查询效率更高:

db.funds.aggregate([
  {
    $match: {
      accountId: ObjectId("替换为实际accountId值"),
      projectId: ObjectId("替换为实际projectId值"),
      aps: "替换为实际aps匹配值"
    }
  },
  // 提前合并三个数组字段,做容错处理
  {
    $project: {
      allIds: {
        $concatArrays: [
          { $ifNull: ["$personalIdRoot", []] },
          { $ifNull: ["$personalIdFill", []] },
          { $ifNull: ["$personalIdCap", []] }
        ]
      }
    }
  },
  // 展开数组
  { $unwind: "$allIds" },
  // 全局去重
  {
    $group: {
      _id: null,
      values: { $addToSet: "$allIds" }
    }
  },
  { $project: { _id: 0 } }
])

容错提示:如果文档中三个数组字段可能存在null、不存在或非数组类型,必须加$ifNull转空数组,否则$concatArrays会抛出类型错误导致聚合失败。

内容的提问来源于stack exchange,提问作者Rohit tdr

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 03:15:38