索引是一种特殊的数据结构,用于快速查找数据。类似于书籍的目录,可以大幅提升查询性能。
// 查看集合的所有索引
db.users.getIndexes()
// 默认返回_id索引
[
{
"v" : 2,
"key" : { "_id" : 1 },
"name" : "_id_"
}
]
// 创建升序索引
db.users.createIndex({ age: 1 })
// 创建降序索引
db.users.createIndex({ age: -1 })
// 创建唯一索引
db.users.createIndex({ email: 1 }, { unique: true })
// 创建稀疏索引(只索引存在该字段的文档)
db.users.createIndex({ phone: 1 }, { sparse: true })
// 创建复合索引(多个字段)
db.users.createIndex({ city: 1, age: -1 })
// 索引顺序很重要!
// 可以支持的查询:
// - { city: "北京" }
// - { city: "北京", age: 25 }
// 不能有效支持:
// - { age: 25 } // 只查询第二个字段
查询条件必须包含索引的前缀字段才能使用索引。例如索引(a, b, c)可以支持查询(a)、(a,b)、(a,b,c),但不能支持(b)或(c)。
| 类型 | 说明 | 示例 |
|---|---|---|
| 单字段索引 | 对单个字段建立索引 | { age: 1 } |
| 复合索引 | 对多个字段建立索引 | { city: 1, age: -1 } |
| 多键索引 | 对数组字段建立索引 | { tags: 1 } |
| 文本索引 | 全文搜索索引 | { content: "text" } |
| 地理空间索引 | 地理位置查询 | { location: "2dsphere" } |
| 哈希索引 | 用于分片键 | { _id: "hashed" } |
// 创建文本索引
db.articles.createIndex({ title: "text", content: "text" })
// 文本搜索
db.articles.find({ $text: { $search: "MongoDB 教程" } })
// 每个集合只能有一个文本索引
// 创建2dsphere索引(地球表面)
db.places.createIndex({ location: "2dsphere" })
// 插入地理数据
db.places.insertOne({
name: "天安门",
location: {
type: "Point",
coordinates: [116.397128, 39.916527] // [经度, 纬度]
}
})
// 查询附近的地点(5公里内)
db.places.find({
location: {
$near: {
$geometry: {
type: "Point",
coordinates: [116.4, 39.9]
},
$maxDistance: 5000 // 米
}
}
})
// unique - 唯一索引
db.users.createIndex({ email: 1 }, { unique: true })
// sparse - 稀疏索引
db.users.createIndex({ phone: 1 }, { sparse: true })
// expireAfterSeconds - TTL索引(自动删除过期文档)
db.sessions.createIndex(
{ createdAt: 1 },
{ expireAfterSeconds: 3600 } // 1小时后自动删除
)
// partialFilterExpression - 部分索引
db.users.createIndex(
{ age: 1 },
{ partialFilterExpression: { age: { $gte: 18 } } }
)
// background - 后台创建(不阻塞数据库)
db.users.createIndex({ name: 1 }, { background: true })
// 删除指定索引
db.users.dropIndex("age_1")
// 删除多个字段的索引
db.users.dropIndex({ city: 1, age: -1 })
// 删除所有索引(除了_id)
db.users.dropIndexes()
// 删除指定的多个索引
db.users.dropIndexes(["age_1", "email_1"])
// 查看查询计划
db.users.find({ age: 25 }).explain("executionStats")
// 关键指标:
// - executionTimeMillis: 执行时间
// - totalDocsExamined: 扫描的文档数
// - totalKeysExamined: 扫描的索引键数
// - stage: "IXSCAN"表示使用了索引,"COLLSCAN"表示全表扫描
// 查看索引统计
db.users.aggregate([{ $indexStats: {} }])
// 电商系统索引设计
// 商品集合
db.products.createIndex({ category: 1, price: 1 }) // 分类浏览
db.products.createIndex({ name: "text" }) // 商品搜索
db.products.createIndex({ sales: -1 }) // 热销排行
// 订单集合
db.orders.createIndex({ userId: 1, createdAt: -1 }) // 用户订单
db.orders.createIndex({ status: 1 }) // 订单状态
db.orders.createIndex(
{ createdAt: 1 },
{ expireAfterSeconds: 7776000 } // 90天后自动删除
)
// 用户集合
db.users.createIndex({ email: 1 }, { unique: true })
db.users.createIndex({ phone: 1 }, { unique: true, sparse: true })