多键索引(数组字段索引)
多键索引的概念
多键索引是MongoDB中专门为数组字段设计的索引类型。当字段包含数组值时,MongoDB会自动为数组中的每个元素创建索引条目,而不是为整个数组创建单个索引条目。这种索引机制使得查询可以高效地匹配数组中的单个或多个元素。
// 示例文档结构
{
_id: 1,
name: "产品A",
tags: ["电子", "数码", "智能家居"],
ratings: [4, 5, 3, 4]
}
多键索引的创建方式
创建多键索引的语法与普通索引相同,MongoDB会自动检测字段是否为数组类型并决定是否创建多键索引:
// 创建多键索引
db.products.createIndex({ tags: 1 })
db.products.createIndex({ ratings: -1 })
// 查看索引信息
db.products.getIndexes()
多键索引的工作原理
当查询条件涉及数组元素时,MongoDB会使用多键索引进行高效查找:
- 对于相等匹配,MongoDB会查找包含指定值的所有数组
- 对于范围查询,MongoDB会检查数组中是否有元素满足条件
- 对于$elemMatch操作符,MongoDB会确保单个数组元素满足所有条件
// 使用多键索引的查询示例
db.products.find({ tags: "电子" })
db.products.find({ ratings: { $gt: 4 } })
db.products.find({
ratings: {
$elemMatch: { $gt: 3, $lt: 5 }
}
})
多键索引的限制
-
一个复合索引中只能有一个数组字段
// 错误的索引创建方式(两个数组字段) db.products.createIndex({ tags: 1, ratings: 1 }) // 报错 // 正确的复合索引(一个数组字段+非数组字段) db.products.createIndex({ tags: 1, name: 1 }) // 成功
-
多键索引不能完全支持覆盖查询
-
哈希索引不能是多键索引
-
多键索引的基数可能很高,影响查询性能
多键索引的性能优化
-
使用$elemMatch确保查询在单个数组元素上操作
// 更高效的查询 db.products.find({ ratings: { $elemMatch: { $gt: 3, $lt: 5 } } })
-
结合非数组字段创建复合索引
db.products.createIndex({ category: 1, tags: 1 })
-
对大型数组使用索引时需谨慎,可能影响写入性能
多键索引的特殊查询场景
-
查询数组长度
db.products.createIndex({ "tags": 1, "ratings": 1 }) db.products.find({ tags: { $size: 3 } }).explain("executionStats")
-
查询数组特定位置的元素
db.products.createIndex({ "ratings.0": 1 }) db.products.find({ "ratings.0": { $gt: 4 } })
-
查询嵌套数组
{ _id: 2, name: "产品B", reviews: [ { score: 5, comment: "优秀" }, { score: 3, comment: "一般" } ] } db.products.createIndex({ "reviews.score": 1 }) db.products.find({ "reviews.score": 5 })
多键索引与文本搜索的结合
当数组包含字符串时,可以创建文本索引进行全文搜索:
db.products.createIndex({ tags: "text" })
db.products.find({
$text: { $search: "电子 数码" }
})
监控多键索引的使用情况
使用explain()方法分析查询是否有效使用了多键索引:
db.products.find({ tags: "电子" }).explain("executionStats")
输出结果中查看:
- stage: "IXSCAN"表示使用了索引扫描
- indexName: 确认使用的索引名称
- keysExamined: 检查的索引键数量
多键索引的存储考虑
- 每个数组元素都会创建一个索引条目
- 大型数组会显著增加索引大小
- 频繁更新的数组字段可能导致索引碎片
// 查看索引大小
db.products.stats()
db.products.totalIndexSize()
多键索引与聚合管道的交互
在聚合管道中,多键索引可以优化$unwind和$match阶段:
db.products.aggregate([
{ $match: { tags: "电子" } }, // 使用多键索引
{ $unwind: "$tags" },
{ $group: { _id: "$tags", count: { $sum: 1 } } }
])
多键索引的删除与重建
删除不再需要的多键索引可以释放存储空间:
db.products.dropIndex("tags_1")
重建索引可以解决碎片问题:
db.products.reIndex()
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:单字段索引与复合索引
下一篇:全文索引与文本搜索