MongoDB 之滴滴、摩拜都在用的索引-educoder上面的题目以及笔记
MongoDB 之滴滴、摩拜都在用的索引
MongoDB 之滴滴、摩拜都在用的索引
(MapReduce的在后面)
第一关:了解并创建一个简单索引
索引的原理:
对某个键按照升续或降续创建索引,查询时首先根据查询条件查找到对应的索引条目,然后找到索引条目对应的文档指针(文档在磁盘上的存储位置),根据文档指针再去磁盘中找到相应的文档,整个过程不需要扫描全表,速度比较快。
每个文档被插入集合时,如果没有给它指定索引_id,MongoDB 会自动给它创建一个默认索引_id,是个 ObjectId 对象
索引基本操作
1、创建索引(单字段索引)
db.person.createIndex({key:1})
- key :要创建索引的键;
- 如果为 1, 按照升序创建索引,而如果为 -1,则是按降序创建索引
2、查询索引
(1).查询集合索引:
db.person.getIndexes()
(2)查询全部索引
db.system.indexes.find()
3、删除索引
(1)通过指定索引名称删除该索引:
db.person.dropIndex("ageIdx")
(2).通过指定集合删除集合中的全部索引:
db.person.dropIndexes()
编程测试代码:
document=([
{_id:1,name: "王小明",age:15,score:90},
{_id:2,name: "周晓晓",age:18,score:86},
{_id:3,name: "王敏",age:20,score:96},
{_id:4,name: "李小亮",age:15,score:74},
{_id:5,name: "张青青",age:21,score:88}
])
db.student.insert(document)
db.student.createIndex({score:-1})
第二关:常见索引的创建
创建常见索引:
创建索引的基本语法: db.集合.createIndex({属性1: 1/-1, 属性2: 1/-1})
1、创建复合索引
和创建单字段索引的方法差不多,只是选取了多个键一同作为索引,中间以逗号隔开:
db.person.createIndex({age: 1, name: 1})
2、创建多 key 索引
当索引的字段为数组时,创建出的索引称为多 key 索引,多 key 索引会为数组的每个元素建立一条索引,比如 person 集合加入一个 habbit 字段(数组)用于描述兴趣爱好:
{name : '王小明', age : 19, habbit: ['football', 'runnning']}
需要查询有相同兴趣爱好的人就可以利用 habbit 字段的多 key 索引。
db.person.createIndex( {habbit: 1} ) // 升序创建多key索引
db.person.find({habbit: 'football'}) //查找喜欢足球的人
3、创建哈希索引
创建命令如下:
4、文本索引的创建与使用
假如我们用 Mongodb 存储了很多博客文章,那么如何快速找到所有关于 mongodb 这个主题的文章呢?这时候就要用到文本搜索了。
(1). 创建文本索引命令:
创建单个字段的文本索引
db.collection.createIndex({ title: 'text'})
- 创建全文本索引的字段必须为 string 格式;
- 每个集合只支持一个文本索引。
创建多个字段的文本索引
db.collection.createIndex(
{
title: 'text',
tags: 'text'
}
)
(2). 使用文本索引;
现在我们已经创建了 title 的索引,我们来搜索一下含有 educoder.net 的文章:
- search 后的关键词可以有多个,关键词之间的分隔符可以是多种字符,例如空格、下划线、逗号、加号等,但不能是-和\,因为这两个符号会有其他用途。搜索的多个关键字是 or 的关系,除非你的关键字包含-;
- 匹配时不是完整的单词匹配,相似的词也可以匹配到;
db.collection.find({$text:{$search:'educoder.net'}})
(3). 删除文本索引
1. 通过命令获取索引名:
db.collection.getIndexes()
- 删除命令:
db.collection.dropIndex('title_text')
编程测试代码(部分):😊
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}])
db.article.createIndex({follwers:1,title:1})
db.article.createIndex({tags:-1})
db.article.createIndex({_id:"hashed"})
db.article.createIndex( { title:'text',tags:'text'})
db.article.getIndexes()
第三关:有趣的地理位置
相关知识:
1、GeoJson 数据
只有拥有特定格式的文档才可以创建。
如果我们用的是 2dsphere 索引,那么插入的应该是 GeoJson 数据。GeoJson 的格式如是:
{ type: ‘GeoJSON type’ , coordinates: ‘coordinates’ }
- type :指的是类型,可以是 Point (本例中用的,点)、LineString(线)、 Polygon(面) 等;
- coordinates :指的是一个坐标数组。
db.locations.insert({_id:1,name:'长沙站',location:{type:'Point',coordinates:[113.018987,28.201215]}})
db.locations.insert({_id:2,name:'湖南师范大学',location:{type:'Point',coordinates:[112.946045,28.170968]}})
db.locations.insert({_id:3,name:'中南大学',location:{type:'Point',coordinates:[112.932175,28.178291]}})
db.locations.insert({_id:4,name:'湖南女子学院',location:{type:'Point',coordinates:[113.014675,28.121163]}})
db.locations.insert({_id:5,name:"湖南农业大学",location:{type:'Point',coordinates:[113.090852,28.187461]}})
2、创建地理位置索引
一般的代码: db.集合.createIndex({创建索引的属性: ’ 2dsphere’ })
- 2d :平面坐标索引,适用于基于平面的坐标计算,也支持球面距离计算,不过官方推荐使用 2dsphere 索引;
- 2dsphere :几何球体索引,适用于球面几何运算;(一般都是用这个!!!)
- 默认情况下,地理位置索引会假设值的范围是从−180到180(根据经纬度设置)。
db.locations.createIndex({location:'2dsphere'})
3、地理位置索引的使用
查询命令:(很重要!!!)
db.runCommand({
geoNear:'locations',
near:{type:'Point',coordinates:[113.018987,28.201215]}, (一般是location)
spherical:true,
minDistance:1000,
maxDistance:8000
})
- geoNear :我们要查询的集合名称;
- near :就是基于那个点进行搜索,这里是我们的搜索点“长沙站”;
- spherical :是个布尔值,如果为 true,表示将计算实际的物理距离,比如两点之间有多少 km,若为 false,则会基于点的单位进行计算 ;
- minDistance :搜索的最小距离,这里的单位是米 ;
- maxDistance :搜索的最大距离。
编程测试代码:
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]}});
db.people.createIndex({personloc:'2dsphere'});
db.runCommand({
geoNear:'people',
near:{type:'Point',coordinates:[116.403981,39.914935]},
spherical:true,
minDistance:100,
maxDistance:3000
});
db.runCommand({
geoNear:'people',
near:{type:'Point',coordinates:[116.433733,39.909511]},
spherical:true,
minDistance:100,
maxDistance:5000
});
db.runCommand({
geoNear:'people',
near:{type:'Point',coordinates:[116.488781,39.949901]},
spherical:true,
minDistance:3000,
maxDistance:8000
});
db.runCommand({
geoNear:'people',
near:{type:'Point',coordinates:[116.342609,39.948021]},
spherical:true,
minDistance:3000,
maxDistance:8000});
MapReduce查询:
操作语法:
db.集合名称.mapReduce(
function(){emit(key, values)}, map:key是需要聚合的属性,values是操作值的属性
function(key, values){return Array.操作(values)}, reduce:操作:sum,avg,min,max,first
{query: 条件,
out: 存储到新的集合的名称,
sort: 条件,
limit: number
}
)
进行查询操作练习:
db.educoder.mapReduce(
function(){emit(this.author,this.learning_num);},
function(key,values){return Array.avg(values)},
{
out:"avg_num"
}
)
db.avg_num.find()
db.educoder.mapReduce(
function(){emit(this.author,this.learning_num);},
function(key,values){return Array.avg(values)},
{
out:"avg_num",
limit:2
}
)
db.avg_num.find()
db.educoder.mapReduce(
function(){
emit(this.author,this.learning_num);
},
function(key,values){
return Array.avg(values)
},
{
query: {author: "李暾"},
out:"avg_num",
}
)
db.avg_num.find()
更多推荐
所有评论(0)