2-3 MongoDB 之滴滴、摩拜都在用的索引
第1关:了解并创建一个简单索引
索引的分类
MongoDB 支持多种类型的索引,主要有以下几种类型:
索引类型 | 用途 |
---|---|
包括单字段索引(Single Field Index) | 针对某一键 key 创建了单字段索引,其能加速对 key 字段的各种查询请求,是最常见的索引形式,MongoDB 默认创建的 id 索引也是这种类型。 |
复合索引 (Compound Index) | 复合索引是单字索引的升级版本,它针对多个字段联合创建索引,先按第一个字段排序,第一个字段相同的文档按第二个字段排序,依次类推。 |
多 key 索引 (Multikey Index) | 当索引的字段为数组时,创建出的索引称为多 key 索引。 |
哈希索引(Hashed Index) | 按照某个字段的hash值来建立索引,目前主要用于 MongoDB Sharded Cluster 的 Hash 分片,哈希索引只能满足字段完全匹配的查询,不能满足范围查询等。 |
地理位置索引(Geospatial Index) | 能很好的解决 O2O 的应用场景,比如:查找附近的美食、查找某个区域内的车站等。 |
文本索引(Text Index) | 能解决快速文本查找的需求,比如有一个博客文章集合,需要根据博客的内容来快速查找,则可以针对博客内容建立文本索引。 |
在 test 数据库创建集合 student
use test;
db.student.insert([{_id:1,name:'王小明',age:15,score:90},{_id:2,name:'周晓晓',age:18,score:86},{_id:3,name:'王敏',age:18,score:86},{_id:3,name:'李晓亮',age:15,score:74},{_id:21,name:'张青青',age:21,score:88}]);
集合中创建成绩的降序索引
db.student.createIndex({score:-1});
第2关:常见索引的创建
在 test2 数据库中创建集合 article
use test2;
db.article.insert([{_id:1,title:'提升程序员工作效率的6个工具利器',tags:['Alfred”,”幕布'],follwers:543},{_id:1,title:'我是如何从零开始学习前端的',tags:['HTML','Html5','CSS'],follwers:1570},{_id:1,title:'20个非常有用的JAVA程序片段',tags:['Java','编程'],follwers:1920}]);
用字段 follwers 和 title 创建复合升序索引
创建复合索引
和创建单字段索引的方法差不多,只是选取了多个键一同作为索引,中间以逗号隔开:
db.article.createIndex({follwers: 1, title: 1})
用字段 tags 创建多 key 降序索引
创建多 key 索引
当索引的字段为数组时,创建出的索引称为多 key 索引,多 key 索引会为数组的每个元素建立一条索引:
db.article.createIndex({tags:-1});
用_id
创建哈希索引
db.article.createIndex({_id:'hashed'});
注:哈希索引涉及知识点太多,本关就不做重点介绍,以后用到再做详细解释。
用字段 title 和 tags 创建文本索引
文本索引的创建与使用
什么时候使用文本索引;
假如我们用 Mongodb 存储了很多博客文章,那么如何快速找到所有关于 mongodb 这个主题的文章呢?这时候就要用到文本搜索了。
db.article.createIndex({title:'text',tags:'text'});
- 创建全文本索引的字段必须为 string 格式;
- 每个集合只支持一个文本索引。
拓展:文本索引的使用
使用文本索引
我们已经创建了 title 的索引,我们来搜索一下含有 educoder.net 的文章:
db.collection.find({$text:{$search:'educoder.net'}})
- search 后的关键词可以有多个,关键词之间的分隔符可以是多种字符,例如空格、下划线、逗号、加号等,但不能是
-
和\
,因为这两个符号会有其他用途。搜索的多个关键字是 or 的关系,除非你的关键字包含-
; - 匹配时不是完整的单词匹配,相似的词也可以匹配到;
删除文本索引
通过命令获取索引名:
db.collection.getIndexes()
删除命令:
db.collection.dropIndex('title_text')
第3关:有趣的地理位置索引
将6个人位置信息插入到数据库 test3 的集合 people 中
use test3;
并不是所有文档都可以创建地理位置索引,只有拥有特定格式的文档才可以创建。
如果我们用的是 2dsphere 索引,那么插入的应该是 GeoJson 数据。GeoJson 的格式如是:
{ type: ‘GeoJSON type’ , coordinates: ‘coordinates’ }
db.people.insert({_id:1,name:'A',personloc:{type:'Point',coordinates:[116.403981,39.914935]}});
db.people.insert({_id:2,name:'B',personloc:{type:'Point',coordinates:[116.433733,39.909511]}});
db.people.insert({_id:3,name:'C',personloc:{type:'Point',coordinates:[116.488781,39.949901]}});
db.people.insert({_id:4,name:'D',personloc:{type:'Point',coordinates:[116.342609,39.948021]}});
db.people.insert({_id:5,name:'E',personloc:{type:'Point',coordinates:[116.328236,39.901098]}});
db.people.insert({_id:6,name:'F',personloc:{type:'Point',coordinates:[116.385728,39.871645]}});
- type :指的是类型,可以是 Point (本例中用的)、LineString、 Polygon 等;
- coordinates :指的是一个坐标数组。
建立地理位置索引 personloc
db.people.createIndex({personloc:'2dsphere'});
- 2d :平面坐标索引,适用于基于平面的坐标计算,也支持球面距离计算,不过官方推荐使用 2dsphere 索引;
- 2dsphere :几何球体索引,适用于球面几何运算;
- 默认情况下,地理位置索引会假设值的范围是从−180到180(根据经纬度设置)。
查询 A 周围100~3000米有哪些人
db.runCommand({
geoNear:'people',
near:{type:'Point',coordinates:[116.403981,39.914935]},
spherical:true,
minDistance:100,
maxDistance:3000
})
查询 B 周围100~5000米有哪些人
db.runCommand({
geoNear:'people',
near:{type:'Point',coordinates:[116.433733,39.909511]},
spherical:true,
minDistance:100,
maxDistance:5000
})
查询 C 周围3000~8000米有哪些人
db.runCommand({
geoNear:'people',
near:{type:'Point',coordinates:[116.488781,39.949901]},
spherical:true,
minDistance:3000,
maxDistance:8000
})
查询 D 周围3000~8000米有哪些人
db.runCommand({
geoNear:'people',
near:{type:'Point',coordinates:[116.342609,39.948021]},
spherical:true,
minDistance:3000,
maxDistance:8000
})
- geoNear :我们要查询的集合名称;
- near :就是基于那个点进行搜索,这里是我们的搜索点“长沙站”;
- spherical :是个布尔值,如果为 true,表示将计算实际的物理距离,比如两点之间有多少 km,若为 false,则会基于点的单位进行计算 ;
- minDistance :搜索的最小距离,这里的单位是米 ;
- maxDistance :搜索的最大距离。