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

如何编写MongoDB聚合管道生成foreignKey-布尔值键值对?

解决MongoDB聚合查询:按指定foreignKey生成存在性布尔值对象

需求回顾

给定一组字符串化的foreignKey ObjectId,生成键为foreignKey、值为布尔值的对象:若该foreignKey在最近x天内有文档(计数>0)则为true,否则为false。

实现步骤与聚合查询

假设集合名为yourCollection,给定的foreignKeys数组为["6001","6002","6003"],x=2天,先完成预处理再执行聚合管道:

// 预处理:转换字符串为ObjectId,计算时间边界
const foreignKeys = ["6001","6002","6003"].map(id => ObjectId(id));
const days = 2;
const timeThreshold = new Date(Date.now() - days * 24 * 60 * 60 * 1000);

// 聚合查询
db.yourCollection.aggregate([
  // 筛选最近x天内、foreignKey在目标数组中的文档
  {
    $match: {
      foreignKey: { $in: foreignKeys },
      createdAt: { $gte: timeThreshold }
    }
  },
  // 按foreignKey分组,标记是否存在文档(只要有1个就为true)
  {
    $group: {
      _id: "$foreignKey",
      exists: { $first: true }
    }
  },
  // 转换为{key: 字符串ID, value: 布尔值}格式
  {
    $project: {
      _id: 0,
      key: { $toString: "$_id" },
      value: "$exists"
    }
  },
  // 收集已存在的key,同时生成包含所有目标key的默认值数组
  {
    $group: {
      _id: null,
      existingKeys: { $push: { k: "$key", v: "$value" } },
      allKeys: { $first: foreignKeys.map(id => ({ k: id.toString(), v: false })) }
    }
  },
  // 合并默认值与实际存在的key结果
  {
    $project: {
      combined: {
        $mergeObjects: [
          { $arrayToObject: "$allKeys" },
          { $arrayToObject: "$existingKeys" }
        ]
      }
    }
  },
  // 输出最终对象
  { $replaceRoot: { newRoot: "$combined" } }
]);

代码解释

  1. 预处理:把字符串ID转为MongoDB原生ObjectId,同时计算最近x天的时间阈值,减少聚合管道内的重复计算。
  2. $match阶段:快速筛选符合条件的文档,缩小后续处理的数据范围。
  3. 第一次$group:按foreignKey分组,用$first: true标记存在性,比统计总数更高效。
  4. $project阶段:将分组结果转为便于转成对象的键值对格式。
  5. 第二次$group:收集所有存在的key,同时生成包含全部目标key、默认值为false的数组。
  6. $mergeObjects + $arrayToObject:合并默认值对象与实际存在的key结果,存在的key会覆盖默认的false。
  7. $replaceRoot:将合并后的对象作为最终输出的根文档。

示例输出

对应题目示例场景,执行后输出:

{
  "6001": true,
  "6002": true,
  "6003": false
}

注意事项

  • 建议为foreignKey和createdAt字段建立复合索引,提升查询效率:
    db.yourCollection.createIndex({ foreignKey: 1, createdAt: -1 });
    
  • 若判断逻辑基于updatedAt,只需将$match中的createdAt替换为updatedAt即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 14:03:20