首页 / MongoDB 入门教程 / $match 与 $project

MongoDB 入门教程

$match 与 $project

本教程共 50 篇 · 第 29 篇 · 更新于 2026-07-30 · 约 7 分钟阅读

MongoDBMongoDB 入门教程matchproject字段重塑重命名

29. $match 与 $project

本节目标:掌握聚合里的 $match 过滤阶段和 $project 重塑阶段,能重命名字段、计算新字段、按需排除 _id,把输出整理成想要的模样。

$match$project 是聚合管道上出场率最高的两个阶段:一个负责「留下哪些文档」,一个负责「每条长什么样」。

db.orders.insertMany([
  { _id: 1001, user_id: 1, status: "completed", total: 657 },
  { _id: 1002, user_id: 2, status: "completed", total: 1099 },
  { _id: 1003, user_id: 1, status: "shipped", total: 597 },
  { _id: 1004, user_id: 3, status: "pending", total: 528 }
])

$match:聚合里的过滤器

$match 的写法和 find 的筛选条件一模一样,支持所有查询运算符:

// 只保留 total 大于 600 的订单
db.orders.aggregate([
  { $match: { total: { $gt: 600 } } }
])

也可以组合多个条件:

// 已完成、且金额大于 600
db.orders.aggregate([
  { $match: { status: "completed", total: { $gt: 600 } } }
])
Note

$match 能用到索引,尤其是写在管道第一位时。所以过滤条件尽量用 $match 表达,别留到后面用 $project 硬筛。

$project:重塑输出结构

$project 决定结果文档保留哪些字段、怎么改名、要不要算新字段。基础用法和 find 的投影很像:

// 只留 user_id 和 total,并去掉 _id
db.orders.aggregate([
  { $project: { _id: 0, user_id: 1, total: 1 } }
])

重命名字段

用一个表达式 "新名": "$旧名" 就能把字段改名。注意引用原字段值时,字段名前要加 $

// 把 user_id 改名为 buyer,total 改名为 amount
db.orders.aggregate([
  { $project: { _id: 0, buyer: "$user_id", amount: "$total" } }
])

计算新字段

$project 里可以用聚合表达式对字段做计算。比如算含税金额(加 10%):

// 新增 amountWithTax 字段,等于 total 乘 1.1
db.orders.aggregate([
  {
    $project: {
      _id: 0,
      user_id: 1,
      amountWithTax: { $multiply: ["$total", 1.1] }
    }
  }
])
Tip

表达式里引用原字段必须写 "$total"(带美元符),字面量直接写数字即可。运算符如 $multiply 接收数组参数。

同时保留、改名与计算

一个 $project 里可以混用保留、改名、算新字段:

db.orders.aggregate([
  {
    $project: {
      _id: 0,
      buyer: "$user_id",          // 改名
      amount: "$total",           // 改名
      amountWithTax: { $multiply: ["$total", 1.1] }  // 计算
    }
  }
])

用 $project 也能「过滤掉」某些文档

如果某个字段是数组或子文档,你还能在 $project 里用 $filter$slice 等表达式进一步裁剪。这属于进阶用法,记住 $project 不只是「选列」,更是「改形」。

Warning

$project 出现在管道中间时,没列出的字段会被丢弃,后续阶段就访问不到了。需要后续阶段用到的字段,要么保留,要么先 $addFields 追加(不丢原字段)。

两阶段配合示例

先过滤已完成订单,再输出精简后的「买家 + 金额 + 含税」结构:

db.orders.aggregate([
  { $match: { status: "completed" } },
  {
    $project: {
      _id: 0,
      buyer: "$user_id",
      amount: "$total",
      amountWithTax: { $multiply: ["$total", 1.1] }
    }
  }
])

$match$project 配合,是绝大多数聚合管道的开头两板斧。下一章看分组统计的核心:$group 与各类累加器。