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

MongoDB聚合管道:为未匹配的ID添加默认文档

解决方案:通过单个聚合管道保留所有指定ID并填充默认值

要实现单个查询保留所有输入ID,同时为未匹配日期条件的ID生成带默认值的文档,核心思路是先将输入的ID数组转为独立文档集合,再与原匹配结果做左连接,确保所有ID都能进入后续的$lookup阶段。

完整聚合管道(MongoDB 5.0+)

[
  // 阶段1:将输入的ID数组转为文档集合
  {
    $documents: [
      { _id: ObjectId("id1") },
      { _id: ObjectId("id2") },
      // 替换为你的<array of ids>中的每个ID,注意转为ObjectId类型
    ]
  },
  // 阶段2:左连接原集合中符合日期条件的文档
  {
    $lookup: {
      from: "你的原集合名称",
      localField: "_id",
      foreignField: "_id",
      let: { targetDate: "2023-03-20" },
      pipeline: [
        {
          $match: {
            $expr: {
              $eq: [
                { $dateToString: { date: "$timestamp", format: "%G-%m-%d" } },
                "$$targetDate"
              ]
            }
          }
        }
      ],
      as: "matchedData"
    }
  },
  // 阶段3:合并匹配结果或填充默认值
  {
    $replaceRoot: {
      newRoot: {
        $mergeObjects: [
          // 默认值模板,根据你的需求修改
          { _id: "$_id", timestamp: null, 其他字段: "默认值" },
          // 如果有匹配数据,取第一个匹配项覆盖默认值
          { $arrayElemAt: ["$matchedData", 0] }
        ]
      }
    }
  },
  // 阶段4:执行原有的lookup关联查询
  {
    $lookup: {
      from: "<somcollection>",
      localField: "_id",
      foreignField: "<foreignId>",
      as: "related"
    }
  }
]

关键阶段说明

  • $documents阶段:直接将输入的ID数组转为文档集合,这是MongoDB 5.0新增的语法,能快速生成基础数据集。如果你的MongoDB版本低于5.0,可以用$unionWith结合空集合的方式替代,或者用$addFields+$unwind生成ID文档。
  • 带子管道的$lookup:这里的$lookup不是直接关联,而是在子管道里完成原有的日期匹配逻辑,只把符合条件的原文档关联过来,实现左连接效果。
  • $replaceRoot+$mergeObjects:将默认值和匹配到的文档合并,没有匹配数据时就保留默认值,确保每个ID都有完整的文档结构进入后续的$lookup。

低版本兼容方案(MongoDB <5.0)

如果无法使用$documents,可以用$facet生成ID文档集合,再做左连接:

[
  {
    $facet: {
      // 生成ID文档集合
      idList: [
        { $addFields: { ids: ["<id1>", "<id2>"] } }, // 替换为你的ID数组
        { $unwind: "$ids" },
        { $project: { _id: { $toObjectId: "$ids" } } }
      ],
      // 获取符合条件的原文档
      matchedDocs: [
        {
          $match: {
            _id: { $in: ["<id1>", "<id2>"] }, // 替换为你的ID数组
            $expr: {
              $eq: [
                { $dateToString: { date: "$timestamp", format: "%G-%m-%d" } },
                "2023-03-20"
              ]
            }
          }
        }
      ]
    }
  },
  { $unwind: "$idList" },
  // 左连接匹配文档
  {
    $lookup: {
      from: "你的原集合名称",
      localField: "idList._id",
      foreignField: "_id",
      as: "matchedData"
    }
  },
  // 合并默认值
  {
    $replaceRoot: {
      newRoot: {
        $mergeObjects: [
          { _id: "$idList._id", timestamp: null, 其他字段: "默认值" },
          { $arrayElemAt: ["$matchedData", 0] }
        ]
      }
    }
  },
  // 执行原lookup
  {
    $lookup: {
      from: "<somcollection>",
      localField: "_id",
      foreignField: "<foreignId>",
      as: "related"
    }
  }
]

这样整个管道就能确保所有输入的ID都能进入$lookup阶段,无需在代码中做二次合并。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 03:47:30