兴城做网站推广的,深圳线运营是网站建设,淄博平台公司,搜狗优化排名学习mongodb#xff0c;体会mongodb的每一个使用细节#xff0c;欢迎阅读威赞的文章。这是威赞发布的第92篇mongodb技术文章#xff0c;欢迎浏览本专栏威赞发布的其他文章。如果您认为我的文章对您有帮助或者解决您的问题#xff0c;欢迎在文章下面点个赞#xff0c;或者关…学习mongodb体会mongodb的每一个使用细节欢迎阅读威赞的文章。这是威赞发布的第92篇mongodb技术文章欢迎浏览本专栏威赞发布的其他文章。如果您认为我的文章对您有帮助或者解决您的问题欢迎在文章下面点个赞或者关注威赞。谢谢。
Mongodb字段允许包含字符文档数组等各种各样的类型。同样Mongodb索引也可以支持字符文档数组等类型。本文结合Mongodb官方文档介绍Mongodb数组类型数据的索引——多键索引。如果应用经常查询数组字段为该字段添加多键索引能够提高查询效率增加索引查询覆盖率优化数据库查询性能。
如在学生集合当中包含了存储学生测验成绩的test_scores字段这个学期的每一次测验成绩都会在这个数组当中。老师需要查询出至少5次测验成绩超过90分的学生 。这样就可以在字段test_scores上添加索引来提高查询效率。因为test_scores是数组类型Mongodb自动为数组类型创建多键索引。
概述
多键索引包含并排序了字段中的数组数据。多键索引能够改善数组字段的查询性能。用户不需要显示的定义多键索引类型。当Mongodb构建索引时看到该字段是数组字段就会自动的创建多键索引。Mongodb可以为普通类型数据数组如字符串数组数字数组和嵌入式文档数据来构建多键索引。如果一个数组包含相同值的多个元素则Mongodb只会选择这些元素中的一个来放入索引当中。
下面的图中描述了多键索引的结构。有一个collection集合字段addr是文档类型的数组。现在为addr数组中的zip字段建立索引。在索引当中数组元素的数值从小到大排列。
语法
使用下面的语句来创建多键索引
db.collection.createIndex({arrayField: sortOrder})
使用和限制
索引边界
在查询中边界定义了索引扫描的各个部分。Mongodb在多键索引边界计算上有特殊的规则详细查看文档《Mongodb多键索引边界》。
唯一多键索引
在唯一多键索引当中文档的数组元素只能包含集合中其他文档数组中不存在的元素。
复合多键索引
在复合多键索引中每一个文档最多只能包含一个被索引的数组字段。
用户不可以为多个数组创建索引。如在集合中包含了下面一个文档数据
{_id: 1, scores_spring:[8, 6], scores_fall:[5,9]}
其中字段scores_spring和字段scores_fall是数组索引用户不能够使用{scores_spring: 1, scores_fall:1}来创建索引。
如果一个复合索引已经存在用户也不能够插入还是索引定义相违背的文档数据。
如集合中包含文档
{_id: 1, scores_spring:[8, 6], scores_fall:9}
{_id: 2, scores_spring:6, scores_fall:[5, 7]}
用户可以创建一个复合多键索引{scores_spring: 1, scores_fall:1}因为每一个文档当中只有一个字段是数组索引不包含这两个字段同时是数组字段的文档数据。该索引创建后Mongodb不允许用户插入两个字段都是数据元素的文档。
排序
基于数组字段的索引进行排序时满足下面两个条件才会使用索引排序而不会在查询中包含一个内存排序。
所有排序字段的值包含在索引边界最大最小值内任何一个与排序模版带有相同前缀的多键索引都不能有边界限制。这句话在文档中很绕口。尝试去理解一下。如前面提到的索引{scores_spring: 1, scores_fall:1}。当某个查询排序使用{sort:{scores_spring:1}},这该排序字段是索引{scores_spring: 1, scores_fall:1}的索引前缀。在查询当中不能对scores_spring做边界限制否者将使用内存排序。
分片集合
多键索引的字段不能作为分片键。但是当分片键是复合索引的前缀时后续索引字段包含数组时这个复合索引就会成为一个符合多键索引。
如下文档, 集合中带有索引{field2:1, field1: 1},当使用field2字段作为分片集的关键字时则field2既是分片关键字也是复合索引的前缀。外国人写的这些英语还是很绕的要理解一下。
{_id:1, field1: [2,8]field2: A}
哈希索引
哈希索引不能是多键索引
索引覆盖查询
多键索引不能覆盖数组字段的查询。但是多键索引能够使用索引前缀覆盖非数组字段的查询。如下面的一个使用案例。
在集合matches中插入文档。
db.matches.insertMany([{ name: joe, event: [open, tournament]},{ name: bill, event: [match, championship]}
])
在name字段和event字段建立索引
db.matches.createIndex({name: 1,event: 1
})
该索引是复合多键索引但是能够覆盖在name字段的查询
db.matches.find({name: joe
}).explain() 使用数组作为查询条件
当查询过滤器中使用整个数组做为查询条件时Mongodb能够使用多键索引查询数组过滤条件中的第一个数组元素但不能使用多键索引去查询整个数组。当Mongodb使用多键索引查询过滤数组中的第一个元素以后所查询出来的文档Mongodb在内存中会对这部分文档进一步过滤过滤出复合查询条件中整个数组的文档。
举例说明一下这个过程。创建集合inventory并插入数据
db.inventory.insertMany([{ _id:5, type: food, item:apple, ratings: [ 5, 8, 9 ] },{ _id:6, type: food, item:banana, ratings: [ 5, 9 ] },{ _id:7, type: food, item:grapes, ratings: [ 9, 5, 8 ] },{ _id:8, type: food, item:orange, ratings: [ 5, 9, 5 ] },{ _id:9, type: food, item:pear, ratings: [ 9, 5 ] }
])
在数组ratings建立多键索引
db.inventory.createIndex({ratings: 1})
构建一个使用数组作为过滤器的查询语句
db.inventory.find({ratings: [5, 9]
}) 在查询计划中能够看出mongodb先使用5通过多键索引查询出所有包含元素5的文档然后在内存中过滤出包含整个数组[5,9]的文档数据
$expr
$expr表达式不支持多键索引
应用
为数值数组添加索引
创建students集合并插入数据。其中 test_scores是数值类型的数组。
db.students.insertMany([{name: Andre Robinson, test_scores: [88, 97]},{name: Alice Martin, test_scores: [62, 73]},{name: Bob Smith, test_scores: [92, 89]}
])
用户经常需要查询出至少有一次测验分数大于90的同学这可以向数组字段添加索引来提高性能
db.students.createIndex({test_scores: 1})
因为字段test_scores是数组类型所以Mongodb自动为该字段创建了多键索引。该索引中包含了字段test_scores的所有值并按照从小到大排列[62, 73, 88, 89, 92, 97].该索引支持在字段test_scores上的查询
如
db.students.find({test_scores: { $elemMatch: { $gte: 90 } }
})
为文档数组添加索引
构建inventory集合并插入数据
db.inventory.insertMany([{item: t-shirt,stock: [{ size: S, quantity: 8 },{ size: L, quantity: 10 }]},{item: sweater,stock: [{ size: S, quantity: 4 },{ size: M, quantity: 7 }]},{item: vest,stock: [{ size: S, quantity: 6 },{ size: L, quantity: 1 }]}
])
用户需要在库存低于5的时候下订单来补货。为了查找出哪些需要补货需要构建语句查出来stock数组中数量quantity少于5的记录。为了提高性能用户需要在字段stock.quantity上添加索引。
db.inventory.createIndex({stock.quantity: 1})
因为stock是包含文档的数组索引Mongodb将这个索引存储为多键索引。该索引将字段stock.quantity所有值按照从小到大排列[1,4,6,7,8,10]
构建语句查询出少于5的数据
db.inventory.find({stock.quantity: { $lt: 5 }})
查询数据按照库存的倒序排列
db.inventory.find().sort({stock.quantity: -1})