首页 / MongoDB 入门教程 / 投影:字段筛选

MongoDB 入门教程

投影:字段筛选

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

MongoDBMongoDB 入门教程投影字段筛选projection查询优化

20. 投影:字段筛选

本节目标:学会用投影文档指定查询只返回需要的字段,掌握抑制 _id 的办法,并理解「包含」和「排除」为什么不能混用。

默认情况下,find 会把匹配文档的所有字段都返回。但很多时候你只想要名字和年龄,不需要邮箱、注册时间那一堆。投影(Projection)就是干这个的:告诉 MongoDB「我只要这些字段」。

// 先确认有数据
db.users.insertMany([
  { _id: 1, name: "张三", email: "zhangsan@example.com", age: 28, city: "北京" },
  { _id: 2, name: "李四", email: "lisi@example.com", age: 34, city: "上海" },
  { _id: 3, name: "王五", email: "wangwu@example.com", age: 22, city: "北京" }
])

投影文档长什么样

find 的第二个参数就是投影文档。字段值写 1 表示「要返回」,写 0 表示「不要返回」:

// 只要 name 和 age 两个字段
db.users.find(
  { city: "北京" },
  { name: 1, age: 1 }
)

返回结果里除了 nameage,还会多一个 _id。这是投影的特殊规则。

_id 默认会返回

_id 是主键,MongoDB 默认总把它带回来,即使你没要求。如果你不想要它,得显式抑制:

// 只要 name 和 age,并且不要 _id
db.users.find(
  { city: "北京" },
  { name: 1, age: 1, _id: 0 }
)

这条返回的就是干净的两列:{ name: "张三", age: 28 }{ name: "王五", age: 22 }

Tip

抑制 _id 是日常查询里最常见的投影操作。接口返回数据给前端时,我经常顺手把 _id 藏起来。

包含与排除互斥

投影有个铁律:要么全写「要」(1),要么全写「不要」(0),不能混着写。唯一例外是 _id,它可以被单独排除。

// 错误示范:同时写了要 age 和不要 email,会报错
db.users.find({ city: "北京" }, { age: 1, email: 0 })

MongoDB 不允许这种「既要又要」。下面两种才合法:

// 写法一:只列出要的字段(含 _id 可选)
db.users.find({ city: "北京" }, { name: 1, age: 1, _id: 0 })

// 写法二:只列出不要的字段,其余全返回
db.users.find({ city: "北京" }, { email: 0, _id: 0 })
Warning

排除写法里 _id 可以额外写 0,但其他字段一旦用了排除,就不能再写任何 1。记住:除了 _id,包含和排除二选一。

投影只减字段,不提速查询

投影发生在数据返回阶段。它减少的是「网络传输的字段量」,并不会让 MongoDB 少扫描文档。真正想加速,要靠索引(后面章节会讲)。

目标投影写法
只要某几列{ 字段: 1, _id: 0 }
不要某几列{ 字段: 0, _id: 0 }
只要非 _id 字段必须逐个列 1

嵌入字段也能投影

内嵌文档的子字段同样可以投影,用点号路径即可:

// 只返回商品名和它的坐标类型
db.products.find(
  {},
  { name: 1, "location.type": 1, _id: 0 }
)

学完投影,你的查询结果就清爽多了。下一章聊聊怎么给结果排序、限制条数,以及做分页。