MongoDB 允许在集合的字段上创建索引,以提高查询效率。索引的作用类似于书的目录,能够加快数据检索速度,避免全表扫描。
1. 创建基本索引
MongoDB 提供 createIndex() 方法来创建索引。
示例
为 name 字段创建索引:
db.products.createIndex({ name: 1 })
1代表升序索引,用于加快按name进行的查询。-1代表降序索引,效果相同,适用于降序排序。
2. 查询索引
查看当前集合的索引:
db.products.getIndexes()
3. 删除索引
删除指定索引:
db.products.dropIndex({ name: 1 })
删除集合中所有索引:
db.products.dropIndexes()
4. 复合索引(Compound Index)
复合索引是对多个字段创建索引,适用于同时查询多个字段的情况。
示例
为 category 和 price 创建复合索引:
db.products.createIndex({ category: 1, price: -1 })
- 按
category升序排序,price降序排序。 - 适用于:
db.products.find({ category: "electronics" })db.products.find({ category: "electronics" }).sort({ price: -1 })
⚠️ 注意:复合索引只能优化索引字段的 “前缀匹配” 查询,例如:
- ✅ 可用索引 →
{ category: "electronics" } - ✅ 可用索引 →
{ category: "electronics", price: { $gt: 100 } } - ❌ 无法使用索引 →
{ price: { $gt: 100 } }(未匹配索引第一个字段)
5. 唯一索引(Unique Index)
唯一索引可防止字段值重复,类似于关系数据库的 UNIQUE 约束。
示例
创建 email 的唯一索引:
db.users.createIndex({ email: 1 }, { unique: true })
⚠️ 注意:
- 如果
email字段已有重复数据,创建唯一索引会失败。 - 需要确保插入数据时不会违反唯一性约束。
6. 部分索引(Partial Index)
部分索引只对满足特定条件的文档建立索引,以减少索引大小并提高查询效率。
示例
仅为 status="active" 的文档创建索引:
db.users.createIndex({ age: 1 }, { partialFilterExpression: { status: "active" } })
7. 稀疏索引(Sparse Index)
默认情况下,索引会包含所有文档,即使某些文档缺少被索引的字段。Sparse Index 仅为包含索引字段的文档建立索引,减少索引存储空间。
示例
为 phone 创建稀疏索引:
db.users.createIndex({ phone: 1 }, { sparse: true })
- 未设置
phone的文档不会被索引。 - 避免不必要的索引存储,但查询时需注意
null值可能不会被索引。
8. TTL 索引(Time-To-Live Index)
TTL 索引用于自动删除过期数据,常用于日志、缓存等场景。
示例
创建 createdAt 字段的 TTL 索引,使文档在 7 天后自动删除:
db.logs.createIndex({ createdAt: 1 }, { expireAfterSeconds: 604800 })
- 需要确保
createdAt存储的是ISODate类型。 - MongoDB 自动定期清理过期数据,无需手动删除。
9. 文本索引(Text Index)
MongoDB 提供全文索引,用于模糊搜索文本。
示例
为 title 和 description 创建全文索引:
db.articles.createIndex({ title: "text", description: "text" })
使用 $text 进行全文搜索:
db.articles.find({ $text: { $search: "mongodb tutorial" } })
⚠️ 注意:
- 一个集合只能有一个文本索引。
- 默认情况下,
text索引不会区分大小写。
10. 地理空间索引(Geospatial Index)
MongoDB 支持 2D 平面和球面坐标索引,常用于地图、LBS(位置服务)等应用。
示例
创建 2D 索引:
db.places.createIndex({ location: "2d" })
创建 2D 球面索引(适用于 GPS 坐标):
db.places.createIndex({ location: "2dsphere" })
查询附近的地点:
db.places.find({
location: {
$near: {
$geometry: { type: "Point", coordinates: [ 40.7128, -74.0060 ] },
$maxDistance: 5000 // 5 公里范围内
}
}
})
11. 查看查询是否使用索引
MongoDB 提供 explain() 方法,查看查询执行计划,分析索引是否生效。
示例
db.products.find({ price: { $gt: 100 } }).explain("executionStats")
如果 "indexScan" 出现,则表示索引被使用,否则 MongoDB 可能进行了全表扫描。
12. 索引最佳实践
✅ 使用索引时需注意:
- 优先索引常查询的字段(如
userId、email)。 - 使用复合索引提高查询效率(如
{ category: 1, price: -1 })。 - 适时删除不必要的索引(避免占用太多存储)。
- 全文搜索使用
text索引(适用于搜索引擎)。 - 查询时确保索引匹配查询顺序,如:
db.products.find({ category: "electronics" }).sort({ price: -1 })
- 这个查询可以使用
{ category: 1, price: -1 }复合索引。
总结
| 索引类型 | 作用 | 示例 |
|---|---|---|
| 单字段索引 | 加速单个字段查询 | { name: 1 } |
| 复合索引 | 适用于多个字段查询 | { category: 1, price: -1 } |
| 唯一索引 | 保证字段唯一性 | { email: 1 }, { unique: true } |
| 部分索引 | 仅对符合条件的文档索引 | { age: 1 }, { partialFilterExpression: { status: "active" } } |
| 稀疏索引 | 仅索引包含该字段的文档 | { phone: 1 }, { sparse: true } |
| TTL 索引 | 让数据自动过期 | { createdAt: 1 }, { expireAfterSeconds: 3600 } |
| 文本索引 | 全文搜索 | { title: "text" } |
| 地理索引 | 位置查询 | { location: "2dsphere" } |
索引的合理使用可以极大提升 MongoDB 查询性能,更多详细内容请关注其他相关文章!