TTL、唯一、稀疏、部分索引
本教程共 50 篇 · 第 45 篇 · 更新于 2026-07-30 · 约 4 分钟阅读
45. TTL、唯一、稀疏、部分索引
本节目标:掌握四种特殊索引属性的用法与边界,知道什么时候该用哪一个。
除了普通索引,MongoDB 还提供几种带「特殊行为」的索引。它们解决的是具体的工程问题,用对了事半功倍。
45.1 TTL 索引:自动过期
TTL(Time To Live,存活时间)索引会在指定时间后自动删除文档。适合存验证码、会话、日志这类「过期即废」的数据。
// 建一个会话集合,并让文档在 created_at 后 1 小时自动删除
test> db.sessions.createIndex(
{ created_at: 1 },
{ expireAfterSeconds: 3600 }
)
插入带时间的会话文档:
test> db.sessions.insertOne({
token: "abc123",
user_id: 1,
created_at: new Date()
})
WarningTTL 靠后台线程定时清理,不是精确到秒。删除可能有分钟级延迟。另外 TTL 字段必须是日期(Date)类型,否则不生效。
45.2 唯一索引:禁止重复
unique: true 保证字段值不重复。我们给 users.email 加唯一约束,防止重复注册。
// 邮箱不可重复
test> db.users.createIndex({ email: 1 }, { unique: true })
再插一个相同邮箱会报错:E11000 duplicate key error。
Note前面提过,
_id上的索引天生唯一且不能删。其它字段要唯一,得显式加unique。
45.3 稀疏索引:跳过缺失文档
普通索引会给每个文档建项,包括字段缺失的。稀疏索引(Sparse Index)只为「字段存在」的文档建项。
// 只为有 nickname 的文档建索引
test> db.users.createIndex({ nickname: 1 }, { sparse: true })
这对「字段多数缺失」的场景能省下大量索引空间,也避免把一堆 null 排在一起。
Tip稀疏索引 + 唯一索引组合,可允许「多个文档都没有该字段」:因为缺失的不会被索引,自然不冲突。想要「有值则唯一、无值随意」就用它。
45.4 部分索引:按条件建索引
部分索引(Partial Index)只给「满足过滤条件」的文档建索引,比稀疏更灵活。靠 partialFilterExpression 指定条件。
// 只为已上架(status: "on")的商品建索引,省空间
test> db.products.createIndex(
{ category: 1 },
{ partialFilterExpression: { status: "on" } }
)
只有 status: "on" 的文档进索引。查询时也带了这个条件,才能命中该部分索引:
test> db.products.find({ category: "外设", status: "on" })
Note部分索引适合「高频查的只是数据的一个子集」的场景,比如只查未完成的订单、只查上架商品。索引变小,写入也更快。
45.5 四种属性一览
| 属性 | 作用 | 典型场景 |
|---|---|---|
| TTL | 到点自动删文档 | 验证码、会话、临时日志 |
| unique | 字段值不重复 | 邮箱、手机号、订单号 |
| sparse | 只为存在字段的文档建索引 | 可选字段、避免 null 聚集 |
| partial | 只为满足条件的文档建索引 | 只查子集(如上架商品) |
45.6 小结
TTL 管自动过期,unique 管不重复,sparse 管「有才建」,partial 管「符合条件才建」。它们都是为特定问题省资源、加约束,按场景取用即可。