Mongodb06 - 索引
1、在任何的数据库之中,索引都是一种提升数据库检索性能的手段,在MongoDB数据库中依然会存在有两种的索引创建:自动创建、手动创建
2、范例:重新创建一个简单的students集合,在students没有设置任何索引,通过getIndexes()函数观察存在的索引内容;=>
db.students.getIndexes(); => 有一个“_id”列的索引内容
3、索引创建:db.集合名称.ensureIndex({列 : 1});
|- 设置的 1 表示索引将按照升序的方式进行排列,降序是 -1;
(01)、范例:创建一个索引,在age字段上 => db.students.ensureIndex({"age": 1});
此时并没有设置索引的名字,索引的名字是自动命名的。命名格式:“字段名称_索引的排序模式”
(02)、针对于age字段上的索引做一个分析 => db.students.find({"age": 19}).explain();
*注:此时的查询使用了索引的技术,但是下面再来观察一个查询,不使用索引查询。
(03)、针对于score字段上设置查询,不使用索引 => db.students.find({"score": {"$gt": 60}}).explain();
*注:此时在score字段上并没有设置索引,当前的索引形式变成了全局扫描的模式。
(04)、如果年龄和成绩一起查询 => db.students.find({"$or": [{"age": {"$gt": 19}},{"score": 60}}).explain();
这个时候虽然age字段上存在有索引,但是有一个很明显的问题,由于score没有索引,依然使用全表扫描,
为了解决此事的问题,可以使用复合索引。
(05)、范例:强制使用索引 => db.students.find({"$or": [{"age": {"$gt": 19}},{"score": {"$gt": 19}}]}).hint({"age": -1, "score": -1}).explain();
如果正常来讲,这个代码根本就不可能调用默认的索引执行,但是我们觉得不好,所以需要使用hint()函数来强制MongoDB告诉你必须使用一次索引,
由于此时在age个score两个字段上已经使用了符合索引,那么现在使用的就是默认的复合索引;
但是如果在一个聚合里面设置了过多的索引,实际上会导致性能下降,可以删除索引;
(06)、删除一个索引 => db.students.dropIndex({"age": -1, "score": -1});
(07)、删除全部索引 => db.students.dropIndexes();
所谓删除全部索引指的就是非“_id”的索引,所有的自定义索引。
4、唯一索引
(01)、唯一索引的主要目的是用在某一个字段上,使该字段的内容不重复。
(02)、创建唯一索引 => db.students.ensureIndex({"name":1},{"unique":true});
在name字段上的内容绝对不允许重复。
(03)、增加一条相同的数据,此时除了name字段上的内容之外,发现所有的数据都不一样,但是由于name字段上设置了唯一的索引,
所以整个程序里面如果增加了重复内容,那么会出现以下的错误内容:
E11000 duplicate key error index: mldn.students.$name
5、过期索引
(01)、在一些程序点会出现若干秒之后信息被删除的情况,例如:手机信息验证;
实现过期索引,但是这个时间往往不怎么准确。
范例:设置过期索引
db.phone.ensureIndex({"time": 1}, {expireAfterSeconds: 10});
设置索引在10秒后过期。
(02)、范例:在一个phones集合里面设置过期索引
如果要想实现过期索引,需要保存一个时间 信息
db.phones.insert({"tel":"110","code":"110","time": new Date()});
*注:等到10秒以后(永远不会那么准确)所保存的数据就会消失,这样的特性在进行一些临时数据保存的时候非常有帮助,
如果没有MongoDB这种特性,而且是使用最简单的关系型数据开发,那么非常麻烦。
5、全文索引
(01)、在一些信息管理的平台上经常需要进行信息模糊查询,最早的时候时候是利用某个字段上实现的模糊查询,但是信息返回不准确,
在MongoDB里面实现简单的全文检索。
(02)、范例:定义一个集合(新闻信息)
db.news.insert({"title":"grh","content":"gry"});
db.news.insert({"title":"grh","content":"gry"});
db.news.insert({"title":"sfq","content":"gry"});
db.news.insert({"title":"fhif","content":"jgasdlkljad"});
(03)、范例:设置全文检索
db.news.ensureIndex({"title":"text","content":"text"});
(04)、范例:实现数据的模糊查询
如果要想表示出全文检索,则使用“$text”判断符,数据查询使用“$search”运算符
|- 查询指定关键字:{"$search":"查询关键字"} => db.news.find({"$text": {"$search":"gry"}});
|- 查询多个关键字(或关系):{"$search":"查询关键字 查询关键字 查询关键字 ...." };
|- 查询多个关键字(与关系):{"$search":"\"查询关键字"\"查询关键字"\"查询关键字"...."}
|- 查询多个关键字(排除一个):{"$search":"查询关键字 查询关键字 查询关键字 .... - " };
(05)、为结果打分 - 分越高越好
打分按照降序排列:db.news.find({"$text": {"$search": "gry"}},{"score":{"$meta":"textScore"}}).sort({"score":{"$meta":"textScore"}}));
按照打分的成绩进行排序,实际上就可以实现更加准去的信息搜索。
(06)、为所有字段设置全文检索 => db.news.ensureIndex({"$**":"text"});
这是一种罪简单的设置全文索引的方式(竟可能别用:慢)
6、地理信息索引
(01)、地理信息索引分为两种:2D平面索引,另外就是2DSphere球面索引。在2D索引中保存的都是坐标,而且坐标保存的就是经纬度坐标。
(02)、范例:定义一个商铺集合
db.shop.insert({"loc": [10,10]});
db.shop.insert({"loc": [11,10]});
db.shop.insert({"loc": [10,11]});
db.shop.insert({"loc": [16,17]});
db.shop.insert({"loc": [50,60]});
db.shop.insert({"loc": [90,90]});
db.shop.insert({"loc": [120,130]});
范例:为shop的集合定义2D索引 => db.shop.ensureIndex({"loc":"2d"});
这个时候shop集合就可以实现坐标位置的查询了,而要进行查询有两种操作:
“$near”查询:查询距离某个点最近的坐标点;
“$geoWithin”查询:查询某个性状内的点;
范例:查询距离坐标[11,11]最近的5个点 => db.shop.find({loc:{"$near":[11,11],"$maxDistance":5}});
但是需要注意,在2D索引里面虽然支持最大距离,不支持最小距离;
但是也可以设置一个查询的范围,使用“$geoWithin”查询,而可以设置几种操作:
矩形范围($box):{"$box": [[x1,y1],[x2,y2]]};
db.shop.find({loc:{"$geoWithin":[[9,9],[11,11]]}});
圆形范围($center):{"$center":[[x1,y1],r]};
多边形($polygon): {"$polygon":[[x1,y1],[x2,y2],[x3,y3],.....]}
(03)、MongoDB里面,除了一些支持的操作函数之外,还有一个重要的命令:runCommand(),
这个函数可以执行所有的特定MongoDB命令。
范例:利用runCommand()实现信息查询 => db.runCommand({"geoNear":"shop", near:[10,10],maxDistance:5,num:2});
这类的命令可以说是MongoDB之中最为基础的命令。