name: mongodb-index-creation version: “2.1.0” description: 掌握 MongoDB 索引创建和类型。学习单字段、复合、唯一、文本、地理空间和 TTL 索引。通过正确的索引显著优化查询性能。 sasmp_version: “1.3.0” bonded_agent: 04-mongodb-performance-indexing bond_type: PRIMARY_BOND
生产级技能配置
capabilities:
- 单字段索引
- 复合索引
- 唯一索引
- 文本索引
- 地理空间索引
- ttl索引
input_validation: required_context: - 集合名称 - 查询模式 optional_context: - 现有索引 - 写入频率 - 集合大小
output_format: index_definition: object creation_command: string impact_analysis: object maintenance_notes: array
error_handling: common_errors: - code: INDEX001 condition: “重复索引” recovery: “检查现有索引,创建前删除重复” - code: INDEX002 condition: “后台索引构建失败” recovery: “检查磁盘空间、内存,使用 background: true 重新构建” - code: INDEX003 condition: “索引过大,内存不足” recovery: “考虑部分索引或移除低价值索引”
prerequisites: mongodb_version: “4.4+” required_knowledge: - 查询模式 - esr-规则 performance_baseline: - “当前查询延迟已记录”
testing: unit_test_template: | // 验证索引创建和使用 await collection.createIndex({ field: 1 }) const indexes = await collection.indexes() expect(indexes.some(i => i.key.field === 1)).toBe(true) const explain = await collection.find({ field: value }).explain() expect(explain.queryPlanner.winningPlan.inputStage.stage).toBe(‘IXSCAN’)
MongoDB 索引创建与类型
通过策略性索引显著提升查询性能。
快速开始
创建索引
// 单字段索引
await collection.createIndex({ email: 1 })
// 复合索引(顺序很重要!)
await collection.createIndex({ status: 1, createdAt: -1 })
// 唯一索引
await collection.createIndex({ email: 1 }, { unique: true })
// 稀疏索引(跳过空值)
await collection.createIndex({ phone: 1 }, { sparse: true })
// TTL 索引(24小时后自动删除)
await collection.createIndex({ createdAt: 1 }, { expireAfterSeconds: 86400 })
// 文本索引(全文搜索)
await collection.createIndex({ title: 'text', content: 'text' })
// 地理空间索引
await collection.createIndex({ location: '2dsphere' })
索引类型
单字段索引
// 一个字段的简单索引
db.users.createIndex({ email: 1 })
// 好处:
// - 加速基于 email 字段的查询
// - 加速基于 email 的排序
// - 加速范围查询:{ $gt, $lt }
// 使用时机:
// - 频繁过滤或排序的字段
// - 高基数(许多唯一值)
复合索引
// 多个字段 - 顺序很重要!
db.orders.createIndex({ status: 1, createdAt: -1 })
// 适用于查询如:
// { status: 'completed', createdAt: {$gt: date} }
// { status: 'completed' } // 可以使用此索引
// 不适用于:
// { createdAt: {$gt: date} } // 索引效果不佳
唯一索引
// 确保字段唯一性
db.users.createIndex({ email: 1 }, { unique: true })
// 防止重复:
// - insertOne 带重复 email → 错误
// - 如果 email 已存在,无法插入
// 稀疏唯一(允许多个空值)
db.users.createIndex({ phone: 1 }, { unique: true, sparse: true })
稀疏索引
// 跳过字段为空或缺失的文档
db.users.createIndex({ phone: 1 }, { sparse: true })
// 好处:
// - 索引更小(排除空值)
// - 匹配查询 { $exists: true }
// 使用时机:
// - 可选字段(非所有文档都有)
// - 减少索引大小
文本索引
// 全文搜索
db.articles.createIndex({
title: 'text',
content: 'text',
tags: 'text'
})
// 查询:
db.articles.find({ $text: { $search: 'mongodb' } })
// 权重(title 比 content 更重要)
db.articles.createIndex({
title: 'text',
content: 'text'
}, { weights: { title: 10, content: 5 } })
地理空间索引
// 2D 球面(经纬度)
db.venues.createIndex({ location: '2dsphere' })
// 查询附近
db.venues.find({
location: {
$near: {
type: 'Point',
coordinates: [-73.97, 40.77]
},
$maxDistance: 5000 // 5公里
}
})
TTL 索引
// 一段时间后自动删除文档
db.sessions.createIndex({ createdAt: 1 }, {
expireAfterSeconds: 3600 // 1小时
})
// 使用案例:
// - 会话过期
// - 临时日志
// - 缓存类集合
// MongoDB 每分钟检查一次
// 删除可能延迟最多 1 分钟
索引管理
列出索引
// 显示所有索引
const indexes = await collection.indexes()
console.log(indexes)
// 显示:名称、键、大小、文档计数
删除索引
// 删除特定索引
await collection.dropIndex('email_1')
// 删除所有非 _id 索引
await collection.dropIndexes()
索引选项
await collection.createIndex({ email: 1 }, {
unique: true, // 强制唯一性
sparse: true, // 跳过空值
background: true, // 不阻塞写入
expireAfterSeconds: 86400, // TTL
collation: { locale: 'en' }, // 语言特定
name: 'custom_name' // 自定义索引名称
})
索引设计:ESR 规则
相等、排序、范围 - 最佳复合索引顺序
// 查询:查找活跃用户,按创建日期排序,年龄 18-65
db.users.find({
status: 'active', // 相等
age: { $gte: 18, $lte: 65 } // 范围
}).sort({ createdAt: -1 }) // 排序
// 最佳索引:
db.users.createIndex({
status: 1, // 相等优先
createdAt: -1, // 排序第二
age: 1 // 范围最后
})
覆盖查询
使查询“覆盖”
// 查询完全从索引返回,无需获取文档!
// 创建包含所有所需字段的索引
db.users.createIndex({ email: 1, name: 1, age: 1 })
// 查询(覆盖 - 无文档获取)
db.users.find(
{ email: 'user@example.com' },
{ projection: { email: 1, name: 1, age: 1, _id: 0 } }
)
// 比获取文档快得多!
监控索引
检查索引使用情况
// MongoDB 4.4+
db.collection.aggregate([
{ $indexStats: {} }
])
// 显示:
// - accesses.ops:使用索引的操作次数
// - accesses.since:索引创建时间
移除未使用索引
// 识别未使用:
// - accesses.ops 值低
// - accesses.since 日期较近
// 删除未使用索引:
await collection.dropIndex('unused_index_name')
最佳实践
✅ 索引设计:
- 为查询索引 - 在频繁过滤的字段上添加索引
- 使用 ESR 规则 - 相等、排序、范围的顺序
- 避免过度索引 - 每个索引都有成本
- 监控索引大小 - 大索引需要内存
- 测试影响 - 测量查询性能
✅ 性能:
- 尽早创建索引 - 在数据增长之前
- 使用 explain() - 验证索引使用(IXSCAN)
- 批量索引创建 - 如果需要多个
- 监控索引统计 - 移除未使用
- 规划增长 - 未来查询模式
❌ 避免:
- 索引所有内容 - 浪费存储和内存
- 无索引的复杂正则表达式 - 总是慢
- 无索引排序 - 内存密集
- 大型文本索引 - 内存使用
- 过时索引 - 不再需要时移除
下一步
- 识别慢查询 - 使用 explain()
- 创建策略性索引 - 针对您的访问模式
- 监控性能 - 前后指标
- 优化复合索引 - ESR 规则
- 移除未使用索引 - 保持精简
准备加速您的 MongoDB! ⚡