Mongodb 聚合命令笔记📒

2024-10-25 18:13:27

本文为阅读 聚合命令官方文档 后做的笔记。

目录:

$addFields

向文档添加新字段,输出包含输入文档中所有现有字段和新添加字段的文档。$set 是 $addFields 的别名。

$addFields 与 $project 区别

$densify

案例1:补齐连续日期数据

集合中每个文档有个日期类型的 create_time 字段,但不连续,希望补充连续的日期数据。

[
  { create_time: new Date('2025-10-20') },
  { create_time: new Date('2025-10-25') },
]

使用 $densify 聚合命令只会在查询结果中补齐缺失的日期数据,集合中还是只有上面两个文档数据。

db.your_collection.aggregate([
  {
    $densify: {
      field: 'create_time',
      range: {
        step: 1,
        unit: 'day',
        bounds: [new Date('2025-10-20'), new Date('2025-10-25')]
      }
    }
  }
])

查询结果如下,

[
  { _id: ObjectId('6901aad1784a3f77d0a6eea9'), create_time: new Date('2025-10-20') },
  { create_time: new Date('2025-10-21') },
  { create_time: new Date('2025-10-22') },
  { create_time: new Date('2025-10-23') },
  { create_time: new Date('2025-10-24') },
  { _id: ObjectId('6901ab7f784a3f77d0a6eeaa'), create_time: new Date('2025-10-25') },
]

$group

案例1:根据日期进行分组并统计数量

集合中每天会添加若干文档,每个文档有个 create_date 字段,希望按照日期进行分组并统计每天的数量。

db.your_collection.aggregate([
  {
    $group: {
      _id: '$create_date',
      count: {
        $sum: 1,
      },
    }
  }
])

$match

过滤集合中的文档。

案例1:集合中 create_time 是个日期类型,仅过滤出 2025 年文档;

db.your_collection.aggregate([
  {
    $match: {
      $expr: {
        $eq: [{ $year: "$create_time" }, 2025]
      }
    }
  }
])

案例2:集合中 create_time 是个日期类型,仅过滤出 2025 年 10 月文档;

db.your_collection.aggregate([
  {
    $match: {
      $expr: {
        $and: [
          { $eq: [{ $year: "$create_time" }, 2025] },
          { $eq: [{ $month: "$create_time" }, 10] }
        ]
      }
    }
  }
])

案例3:集合中 create_time 是个日期类型,仅过滤出 2025 年 7-10 月文档;

db.your_collection.aggregate([
  {
    $match: {
      $expr: {
        $and: [
          { $eq: [{ $year: "$create_time" }, 2025] },
          { $gte: [{ $month: "$create_time" }, 7] },
          { $lte: [{ $month: "$create_time" }, 10] }
        ]
      }
    }
  }
])

$project

过滤字段,可以是文档现有字段,也可以是新添加的计算字段,_id 字段默认返回。

db.user.insertMany( [
  {
    first_name: '张',
    last_name: '三',
    gender: 'male',
    age: 18,
  },
  {
    first_name: '李',
    last_name: '四',
    gender: 'female',
    age: 20,
  },
] )

案例1:返回原字段,值为 1 表示返回该字段,值为 0 表示不返回该字段;

db.your_collection.aggregate([
  {
    $project: {
      gender: 1,          // 保留原字段
      _id: 0             // 隐藏默认的 _id 字段
    }
  }
])

运行管理返回如下结果:

[
  {
    gender: 'male',
  },
  {
    gender: 'female',
  },
]

案例2:返回计算字段

返回 uesrname 字段,值为 first_name + last_name

db.your_collection.aggregate([
  {
    $project: {
      username: { 
        $concat: ["$first_name", "$last_name"]  // 拼接生成新字段
      },
      _id: 0             // 隐藏默认的 _id 字段
    }
  }
])

运行管道返回如下结果:

[
  {
    username: '张三',
  },
  {
    username: '李四',
  },
]

案例3:既返回原字段,又返回计算字段

返回 gender 和 age 原字段,返回 uesrname 计算字段,值为 first_name + last_name

db.your_collection.aggregate([
  {
    $project: {
      gender: 1,          // 保留原字段
      age: 1,
      username: { 
        $concat: ["$first_name", "$last_name"]  // 拼接生成新字段
      },
      _id: 0             // 隐藏默认的 _id 字段
    }
  }
])

运行管道返回如下结果:

[
  {
    gender: 'male',
    age: 18,
    username: '张三',
  },
  {
    gender: 'female',
    age: 20,
    username: '李四',
  },
]

案例4:什么情况使用 $addFields 代替 $project

如果一个文档有100个字段,我要返回100个原字段和1个计算字段,理论上我需要将100个字段全部列出来,值设置为1
db.your_collection.aggregate([
  {
    $project: {
      gender: 1,          // 保留第1个原字段
      age: 1,             // 保留第2个原字段
      ...
      ...                 // 保留第100个原字段
      username: { 
        $concat: ["$first_name", "$last_name"]  // 拼接生成新字段
      },
    }
  }
])

可以使用 $addFields 或者 $set,默认会返回所有原字段,你只需添加计算字段即可。

db.your_collection.aggregate([
  {
    $addFields: {
      username: { 
        $concat: ["$first_name", "$last_name"]  // 拼接生成新字段
      },
    }
  }
])

你可能会说 100 个原字段里我不要 _id,再加一个管道就好了

db.your_collection.aggregate([
  {
    $addFields: {
      username: { 
        $concat: ["$first_name", "$last_name"]  // 拼接生成新字段
      },
    }
  },
  {
    $project: {
      _id: 0             // 隐藏默认的 _id 字段
    }
  }
])

$set

$set 是 $addFields 的别名,用于向文档添加新字段,输出包含输入文档中所有现有字段和新添加字段的文档。

返回首页

本文总阅读量  次
皖ICP备17026209号-3
总访问量: 
总访客量: