为什么要有索引
查问快! 查问快!查问快!
MongoDB 的 10 种索引?
创立索引语法:
db.<collection_name>.createIndex(<key and index type specification>, <options>)
咱们的 record Collection 存在如下 document
{"_id": ObjectId("570c04a4ad233577f97dc459"),
"score": 1034,
"userId": 123,
"location": {state: "ZH", city: "ChengDu"},
"addr": [{zip: "10036", detail: "高家村五组"},
{zip: "94231", detail: "王家镇三组 701"}
]
}
_id 索引
mongodb 会主动为 document 中的_id 字段加上索引,所以能用_id 查问就用_id 查问
单键索引
db.records.createIndex({ score: 1})
复合索引
db.records.createIndex({ userId: 1, score: 1})
多值索引
db.records.createIndex({ "addr.zip": 1})
天文空间索引
MongoDB 为坐标立体查问提供了专门的索引,称为天文空间索引。这种查问须要两个维度,所以参数是 2d。
db.map.ensureIndex({"gps" : "2d"});
gps 键的值必须是某种模式的一对值:一个蕴含 2 个元素的数组或者是蕴含 2 个键的内嵌文档
{"gps" : [0,100]}
{"gps" : {"x" : -30 , "y" : 30}}
{"gps" : {"latitude" : -180, "longitude" : 180}}
至于键名能够随便。默认状况下,天文空间索引假如值范畴是 -180~180(对经纬度来说很不便), 咱们同样能够应用参数来对索引进行定制, 比方上面的星图
db.star.trek.ensureIndex({"light-years" : "2d"} , {"min" : -1000, "max" : 1000, bits;10},{collation: {locale: "simple"}});
下面的 bits 指定的是索引精度,默认状况下 2d index 应用的是 26 位精度,在默认范畴 -180~180 中, 大概等于 60cm 误差,最大能够设置 32 位精度。
索引精度不影响查问精度,升高精度的长处是插入操作的解决开销较低,并且占用的空间更少。较高精度的长处是查问扫描索引的较小局部以返回后果。
collation(排序规定)容许用户为字符串比拟指定特定于语言的规定,例如字母和重音符号的规定。
天文空间的查问须要 $near,它须要两个目标值的数组作为参数
db.map.find({"gps" : {"$near" : [40,-73]}}).limit(10);
默认查 100 个文档,如果不须要这么多,就应该设置一个少点的值以节约资源。
还能够应用
db.runCommand({geoNear : "map", near: [40,-73],num : 10})
geoNear 的形式会返回每个文档到查问点的间隔。
还能够查问矩形和圆形内所有的点, 这个时候就要将原来的 $near 换成 $geoWithin .
对于矩形要应用 $box 选项,它的参数是 2 个元素的数组,第一个元素指定了左下角坐标,第二个指定了右上角坐标
db.map.find({"gps" : {"$geoWithin" : {"$box" : [[10,20],[15,30]]}}});
如果要查问圆形,则要应用 $center,参数变成了圆心和半径
db.map.find({"gps" : {"$geoWithin" : {"$center" : [[12,25],5]}}});
天文空间查问既能够应用平面几何,也能够应用球面几何,依据应用的查问和索引类型来决定。2dsphere 索引只能反对球面几何,而 2d 索引同时反对立体和球面几何。
然而,在 2dsphere 索引上应用球面几何的查问将会更高效和精确。
2dsphere : https://docs.mongodb.com/manu…
它的利用场景能够是 查找左近美食,查找左近停车场等数据。
全文索引
创立索引:
db.<collection_name>.createIndex({<key>: "text"});
查问数据:
db.<collection_name>.find({ $text: { $search: "green"} } );
查问以及排序:
db.<collection_name>.find(
{
"$text": {"$search": "green"}
},
{
"textScore": {"$meta": "textScore"}
}
).sort({
"textScore": {"$meta": "textScore"}
})
留神这里的 textScore 并不是汇合中的某个字段,而是 mongodb 依据搜寻后果计算该条数据的分数(匹配度预报, 值越大)
TTL 索引
我在之前的文章讲到过这个索引,它实际上是一个具备生命周期的索引, 这种索引容许为每一个文档设置一个超时工夫。一个文档达到预设置的老化水平后就会被删除。
db.user_session.createIndex({"updated":1},{expireAfterSeconds:60*60*24});
如果一个文档的 updated 字段存在并且它的值是日期类型,当服务器工夫比文档的 updated 字段的工夫晚 expireAfterSeconds 秒时,文档就会被删除
db.getCollection('user_session').insert(
{_id: NumberInt(1),
"updated":new Date(),
username:'lisi'
}
);
局部索引
db.<collection_name>.createIndex({'wechat': 1},
{
"partialFilterExpression": {
"wechat": {"$exists": true}
}
}
)
下面的索引示意对存在 wechat 字段的文档进行索引。局部索引仅索引汇合中合乎指定过滤器表达式的文档,升高了索引创立和保护的性能老本。
局部索引提供了稠密索引性能的超集,应优先于稠密索引应用
稠密索引
db.addresses.createIndex({ "xmpp_id": 1}, {sparse: true} )
索引不索引不蕴含 xmpp_id 字段的文档。
哈希索引
db.collection.createIndex({ _id: "hashed"})
哈希索引指依照某个字段的 hash 值来建设索引,目前次要用于 MongoDB Sharded Cluster 的 Hash 分片,hash 索引只能满足字段齐全匹配的查问,不能满足范畴查问
后盾形式创立索引
db.<collection_name>.createIndex(<key and index type specification>, {background: true})
建设索引即耗时也费劲,还须要耗费很多资源。应用 {background: true} 选项能够使这个过程在后盾实现,同时失常解决申请。要是不包含这个选项,数据库会阻塞建设索引期间的所有申请。
阻塞的做法会让索引建设得更快,同时也意味着利用在此期间不能应答。即使后盾进行也会对失常操作有些影响,所以最好选在无关紧要的时刻。后盾创立索引也会减少负载,好在不会让服务器宕机。
不过从 4.2 版本开始, 所有索引构建都应用优化的构建过程,该过程仅在构建过程的开始和完结时才持有排他锁。其余的构建过程将产生交织的读写操作。如果指定该属性,MongoDB 将疏忽这个选项。