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

MongoDB中值为数组的Map类型字段聚合查询实现方案

MongoDB聚合实现两种联系方式视图输出

需求1:按联系方式类型生成独立字段的输出

对应示例中每个联系方式单独成文档,字段名对应联系方式类型的聚合管道:

db.collection.aggregate([
  // 将contactInfo转换为k-v数组,空Map转为空数组
  {
    $addFields: {
      contactEntries: {
        $cond: {
          if: { $eq: ["$contactInfo", {}] },
          then: [],
          else: { $objectToArray: "$contactInfo" }
        }
      }
    }
  },
  // 拆分每个联系方式类型,保留空/无数据的文档
  {
    $unwind: {
      path: "$contactEntries",
      preserveNullAndEmptyArrays: true
    }
  },
  // 拆分每个联系方式值(数组拆为单个元素),保留空数组的情况
  {
    $unwind: {
      path: "$contactEntries.v",
      preserveNullAndEmptyArrays: true
    }
  },
  // 合并姓名与动态联系方式字段,处理空数据场景
  {
    $project: {
      _id: 0,
      result: {
        $mergeObjects: [
          { name: "$name" },
          {
            $cond: {
              if: "$contactEntries",
              then: { $arrayToObject: [[{ k: { $toLower: "$contactEntries.k" }, v: "$contactEntries.v" }]] },
              else: {}
            }
          }
        ]
      }
    }
  },
  // 替换根节点为结果文档
  { $replaceRoot: { newRoot: "$result" } },
  // 去重,避免空contactInfo时生成重复的仅姓名文档
  { $group: { _id: "$name", doc: { $first: "$$ROOT" } } },
  { $replaceRoot: { newRoot: "$doc" } }
])

关键步骤说明:

  • $objectToArray将Map结构的contactInfo转为k-v数组,空Map通过$cond转为空数组,避免后续操作报错。
  • 两次$unwind分别拆分联系方式类型和数组元素,preserveNullAndEmptyArrays保证空数据文档不被过滤。
  • $arrayToObject动态生成联系方式字段,$toLower将类型名转为小写(如Email→email),不需要可移除。
  • 最终$group去重,解决空contactInfo场景下重复生成仅姓名文档的问题。

需求2:统一格式输出contactType和contactInfo字段

对应要求的{name, contactType, contactInfo}格式的聚合管道:

db.collection.aggregate([
  {
    $addFields: {
      contactEntries: {
        $cond: {
          if: { $eq: ["$contactInfo", {}] },
          then: [],
          else: { $objectToArray: "$contactInfo" }
        }
      }
    }
  },
  {
    $unwind: {
      path: "$contactEntries",
      preserveNullAndEmptyArrays: true
    }
  },
  {
    $unwind: {
      path: "$contactEntries.v",
      preserveNullAndEmptyArrays: true
    }
  },
  // 生成统一格式字段
  {
    $project: {
      _id: 0,
      name: "$name",
      contactType: { $cond: { if: "$contactEntries", then: { $toLower: "$contactEntries.k" }, else: null } },
      contactInfo: "$contactEntries.v"
    }
  },
  // 处理空数据场景,仅保留姓名
  {
    $addFields: {
      result: {
        $cond: {
          if: "$contactEntries",
          then: { name: "$name", contactType: "$contactType", contactInfo: "$contactInfo" },
          else: { name: "$name" }
        }
      }
    }
  },
  { $replaceRoot: { newRoot: "$result" } },
  // 去重,避免重复文档
  { $group: { _id: { name: "$name", contactType: "$contactType", contactInfo: "$contactInfo" }, doc: { $first: "$$ROOT" } } },
  { $replaceRoot: { newRoot: "$doc" } }
])

关键步骤说明:

  • 前半部分拆分逻辑与需求1一致,确保所有边界场景被覆盖。
  • $project直接生成contactType和contactInfo字段,空数据场景下contactType设为null,也可根据需求调整。
  • $cond判断是否存在有效联系方式,空场景下仅保留姓名字段。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 10:53:11