MongoDB–特殊的索引
文章目录
一:TTL索引
1. 简介
如果想要控制删除集合,就可以使用TTL索引。TTL索引可以支持文档在一定时间之后自动过期删除,目前TTL索引只能在单字段上建立,并且字段类型必须是date类型或者包含有date类型的数组(如果数组中包含多个date类型字段,则取最早时间为过期时间)
2. 机制
-
当你在集合中某一个字段建立TTL索引后,后台会有一个单线程,通过不断查询(默认60s一次)索引的值来判断document是否有过期
-
删除文档的动作还依据mongod实例的负载情况,如果负载很高,可能会稍微延后一段时间再删除
-
在复制集成员中,TTL后台线程只删除primary的过期数据,如果此实例变为secondary角色,则后台线程闲置
3. TTL的使用
3.1 固定集合的TTL
db.createCollection("capped",{"capped":true,"size":100,"max":5})//创建固定集合
var date=new Date()//得到date数据
db.capped.insert([{"_id":1,"date":date},{"_id":2,"date":date},{"_id":3,"date":date}]) //插入集合
db.capped.insert([{"_id":1,"date":new Date()},{"_id":2,"date":new Date()},{"_id":3,"date":new Date()}])
db.capped.ensureIndex({"date":1},{expireAfterSeconds:60 }) //添加TTL索引,时间单位是秒
查看索引:
cqsm>db.capped.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "cqsm.capped"
},
{
"v" : 2,
"key" : {
"date" : 1
},
"name" : "date_1",
"ns" : "cqsm.capped",
"expireAfterSeconds" : 180
}
]
到达时间后发现,固定集合中并没有删除文档;得出结论TTL索引对于固定集合无效。
3.2 动态集合的TTL
db.capped.drop()//删除掉集合
db.capped.insert([{"_id":1,"date":date},{"_id":2,"date":date},{"_id":3,"date":date}]) //插入集合
db.capped.ensureIndex({"date":1},{expireAfterSeconds:60 }) //添加TTL索引,时间单位是秒
cqsm>db.capped.find() //查看集合
{ "_id" : 1, "date" : ISODate("2019-11-27T02:36:51.850Z") }
{ "_id" : 2, "date" : ISODate("2019-11-27T02:36:51.850Z") }
{ "_id" : 3, "date" : ISODate("2019-11-27T02:36:51.850Z") }
到达时间后:文档被删除
cqsm>db.capped.find()
cqsm>
4. 限制条件
有一下集中情况是无法使用TTL索引的
-
TTL索引是单字段索引,混合索引不支持TTL,并且也会忽略expireAfterSeconds属性
-
在_id 主键上不能建立TTL索引
-
在capped collection中(固定集合)不能建立TTL索引,因为MongoDB不能从capped collection中删除文档
-
不能使用createIndex()去更改已经存在的TTL索引的expireAfterSeconds值,如果想更改expireAfterSeconds,可以使用collMod命令,否则你只能删除索引,然后重建
-
不能在已有索引的字段上再创建TTL索引了,如果你想把非TTL索引改为TTL索引,那就只能删除重建索引了
5. 使用collMod命令修改expireAfterSeconds值
db.runCommand({"collMod":"apped","expireAfterSeconds":300})
二:全文本索引
1. 全文本索引简介
全文本索引是对文本文件中的字段加索引。
使用全文本索引可以快速的进行文本搜索。但是创建全文本的索引的成本高。
- 任何一个操作频繁的集合上创建全文本索引可能会导致MongDB过载,最好离线的时候创建全文本索引
- 全文本索引的集合的写入速度很慢
- 全文本索引会降低分片时候的数据迁移速度
- 一个集合上最多只能有一个全文本索引,但是全文本索引可以包含多个字段
- 全文本索引的字段顺序不重要,每个字段被同等对待,但是可以设置权重(索引一旦创建之后就不能改变权重了)
MongoDB 在 2.6 版本以后是默认开启全文检索的,如果你使用之前的版本,你需要使用以下代码来启用全文检索:
>db.adminCommand({setParameter:true,textSearchEnabled:true})
2. 创建全文本索引
2.1 单键全文索引
如下文件:
cqsm>db.mong.find()
{ "_id" : ObjectId("5dde12748ead21d246cc04a6"), "title" : "hello everyone aa is me" }
{ "_id" : 2, "title" : "aa hello everyone is me sdwd" }
{ "_id" : ObjectId("5dda60627a8eb11f45c1599d"), "title" : "ba a aa" }
{ "_id" : ObjectId("5dda60ac7a8eb11f45c159a2"), "eat" : 22 }
针对title字段建立索引
db.mong.ensureIndex({"title":"text"})
使用全局文本索引模糊查询单个关键词
db.mong.find({$text:{$search:"aa"}})//加不加" "都行
返回结果:
cqsm>db.mong.find({"$text":{$search:"aa"}})
{ "_id" : ObjectId("5dda60627a8eb11f45c1599d"), "title" : "ba a aa" }
{ "_id" : ObjectId("5dde12748ad21d246cc04a6"), "title" : "hello everyone aa is me" }
{ "_id" : 2, "title" : "aa hello everyone is me sdwd" }
使用全局文本索引模糊查询多个关键词,满足其中一个就行
db.mong.find({$text:{$search:"aa is"}})
使用全局文本索引模糊查询同时含有多个关键词
db.mong.find({$text:{$search:" \"aa\" \"is\" "}})
不包含某个字段可以使用负号(3.6 版本不可以使用)
db.mong.find({$text:{$search:"-is aa"}})
2.2 复合全文索引
db.articles.ensureIndex({key_1:'text',key_2:'text'})
2.3 全文索引
在不知道文档包含的字段的情况下,可以使用"$**"在文档的所有字符串字段上创建全文本索引,这样也会对内嵌文档和数组上所有的字符串字段建立索引。
db.articles.ensureIndex({"$**":"text"})
2.4 设置权重
db.mong.ensureIndexes({"title":"text","desc":"text"},{"weight":{"title":3,"desc":2}})
2.6 优化全文本搜索
创建一个复合索引,普通索引+全文索引
db.mong.ensureIndexes({"name":1,"title":"text"})
使用前缀和后缀的形式创建复合索引
db.mong.ensureIndexes({"name":1,"title":"text","age":1})
注意:一个集合只能有一个全文索引,前缀索引字段和后缀索引字段都不可以是多键字段。
三:地理空间索引
MongoDB支持几种类型的地理空间索引,其中最常用的就是2dsphere索引(用于地球表面类型的地图)和2d索引(用于平面地图和时间连续的数据)
后面的博客详细介绍和学习。