七. 分页与排序
1. limit 返回指定的数据条数
//查询出persons文档中前5条数据
db.persons.find({},{_id:0,name:1}).limit(5)
2. skip 返回指定数据的跨度
//查询出persons文档中5至10条的数据
db.persons.find({},{_id:0,name:1}).limit(5).skip(5)
3. sort 返回按照年龄排序的数据[1,-1]
db.persons.find({},{_id:0,name:1}).limit(5).skip(5).sort({age:1})//1为正序
db.persons.find({},{_id:0,name:1}).limit(5).skip(5).sort({age:-1})//-1为倒序
注: mongodb的key可以存不同类型的数据,排序也有优先级
最小值->null->数字->字符串->对象/文档->数组->二进制->对象ID->布尔值->日期->时间戳->正而->最大值
(建议:设计时统一数据类型)
4. limit和skip完成分页
//每页三条数据
第一页:db.persons.find({},{_id:0,name:1}).limit(3).skip(0)
第二页:db.persons.find({},{_id:0,name:1}).limit(3).skip(3)
//skip会影响性能,尽量要少用,可以换个思路
_id name age date
001 Jim 25 2015-11-03:12:54:25
002 Tom 34 2015-11-04:12:20:25
003 Lili 21 2015-11-05:12:14:25
004 Zhang 23 2015-10-03:12:34:25
005 Wang 26 2015-10-03:12:20:25
006 Zhao 29 2015-09-03:12:29:25
*每次查询操作的时候,前后台传值要把上次的最后一个文档的日期保存下来
db.persons.find({date:{$gt:日期数值}}).limit(3)
(另:应该把重点放在便捷和精确查询上,而不是分页的性能,因为用户一般不会翻查2页))
八. 游标
1. 利用游标遍历查询数据,游标只读取一遍
varpersons=db.persons.find();
while(persons.hasNext()){
obj=persons.next();
print(obj.name)
}
2. 游标销毁条件:1.客户端发来信息要销毁,2.游标迭代完毕,3.默认游标超过10分钟没使用
3. 查询快照 $snapshot:true
快照后就会针对不变的集合进行游标运动,使用快照可以不修改原来的集合,避免修改后的数据出现混乱
db.persons.find({$query:{name:”Jim”},$snapshot:true})
九. 索引
1. 创建索引
数据准备 index.js
~~for(vari=0;i<200000;i++){
db.books.insert({number:i,name:i+”book”})
}
20万数据,差不多用时7秒
先检验查询性能
var start=new Date()
db.books.find({number:65871}) //查询65871条数据
var end=new Date()
end-start
//用时102毫秒
为number创建索引
db.books.ensureIndex({number:1})
再输入查询65871条数据,用时12毫秒
2. 索引使用注意
db.books.ensureIndex({number:1})
1 为正序创建索引
-1 为倒序创建索引
2.1 创建索引可以提高查询性能,但影响插入性能所以对于多查少插的文档可以考虑使用
2.2 全键都建索引不一定能提高性能
2.3做排序工作如果数据量大可以加索引,提高排序性能
3. 索引的名称
3.1用VUE查看索引名称
//number:1
3.2 创建索引同时指定索引的名字
db.books.ensureIndex({name:-1},{name:”bookname”})
4. 唯一索引
4.1 解决文档books不能插入重复的数值
建立唯一索引后不能再插入重复的数值
db.books.ensureIndex({name:1},{unique:true})//建立索引
试验
db.books.find({name:”0book”}) ///能找到
db.books.insert({name:”0book”}) ///报错
5. 踢出重复值
如果创建唯一索引前,已有重复数据, dropDups:true会自动删除重复的索引
db.books.ensureIndex({name:-1},{unique:true,dropDups:true})
6. Hint
强制查询指定的索引
db.books.find({name:”1book”,number:1}).hint({name:-1})
指定索引必须是已经创建了的索引,正序用1查,倒序用-1查
7. expain
详细查看本次查询使用的索引和查询数据的状态信息
db.books.find({name:”1book”}).explain()
// “cursor”:”BtreeCursorname_-1” 本次查询使用的索引
//”nscanned”:1 查询的文档数目
//”millis”:0 查询消耗的时间, 0是很不错的性能
8. 索引管理
8.1 system.indexes 在shell查看数据库已经建立的索引
db.system.indexes.find()
db.system.namespaces.find()//查询出来的不是一个集合
8.2 后台执行 执行创建索引的过程会暂时锁表,所以为了不影响执行,可以设置在后台执行索引的创建过程
db.books.ensureIndex({name:-1},{background:true})
8.3 删除索引
批量和精确删除索引( runCommand可以执行任何特殊命令)
db.renCommand({dropIndexes:”books”,index:”name_-1”})//精确删除
db.runCommand({dropIndexes:”books”,index:”*”}) //批量删除
十. 空间索引
1. 利用空间索引查询地理坐标
数据准备 map.json //gis[x,y]
1.1 查询出距离点(70,180)最近的3个点
//添加2D索引
db.map.ensureIndex({“gis”:”2d”},{min:-1,max:201})
//如不写坐标,默认会建立一个[-180,180]之间的2D索引
查询点(70,180)最近的3个点
db.map.find({“gis”:{$near:[70,180]}},{gis:1,_id:0}).limit(3)
1.2 查询以点(50,50)和点(190,190)为对角线的正方形中的所有的点
db.map.find({gis:{“$within”:{$box:[[50,50],[190,190]]}}},{_id:0,gis:1})
1.3 查询以圆心为(56,80)半径为50规则下的圆心面积中的点
db.map.find({gis:{$within:{$center:[[56,80],50]}}},{_id:0,gis:1})
十一. Count + Distinct + Group
1. Count 计数
//请查询persons美国学生的人数
//db.persons.find().count()总人数
db.persons.find({country:”USA”}).count()
2. Distinct 不同/过滤相同值/去重
//请查询persons中一共有多少个国家,分别是什么
db.runCommand({distinct:”persons”,key:”country”}).values
3. Group 分组
语法:
db.runCommand({group:{
ns:集合名字,
key:分组的键对象,
initial:初始化累加器,
$reduce:组分解器, //
condition:条件,
finalize:组完成器
}})
//分组首先会按照key进行分组,每组的每一个文档都要执行$reduce方法
//接收两个参数,一个是组内本条记录,一个是累加器数据
3.1 请查出persons中每个国家数学成绩最好的学生(必须90以上)
//$reduce分解器
//先把国家分组,再对比数学成绩
db.runCommand({group:{
ns:”persons”,
key:{“country”:true},
initial:{m:0},
$reduce:function(doc,prev){ //分解器,分开对比,累加
If(doc.m>prev.m){
prev.m=doc.m;
prev.name=doc.name;
prev.country=doc.country;
}
},
condition:{m:{$gt:90}} /设定条件,过滤
}})
3.2 在3.1要求的基础上把每个人的信息连接起来写一个描述赋值到m上
// finalize 完成器
db.runCommand({group:{
ns:”persons”,
key:{“country”:true},
initial:{m:0},
$reduce:function(doc,prev){ //分解器,分开对比,累加
If(doc.m>prev.m){
prev.m=doc.m;
prev.name=doc.name;
prev.country=doc.country;
}
},
finalize:function(prev){ //完成器,用m代替原有的长字符串
prev.m=prev.name+”Mathscores”+prev.m
},
condition:{m:{$gt:90}} /设定条件,过滤
}})
4. 用函数格式化分组的键
4.1 如果集合中出现键country 和counTry同时存在,那么分组就会麻烦,
//$keyf
db.runCommand({group:{
ns:”persons”,
$keyf:function(doc){
If(doc.counTry){
return{country:doc.counTry}
}else{
return{country:doc.country}
}
},
Initial:{m:0},
$reduce:function(doc,prev){
If(doc.m>prev.m){
prev.m=doc.m;
prev.name=doc.name;
if(doc.country){
prev.country=doc.country;
}else{
prev.country=doc.counTry;
}
}
},
finalize:function(){
prev.m=prev.name+”Math scores”+prev.m
},
condition:{m:{$gt:90}}
}})
十二. 数据库命令操作
1. 命令执行器 runCommand
1.1 用命令执行完成一次删除表的操作
//删除map
db.runCommand({drop:”map”}){
“nIndexesWas”:2,
“msg”:”indexes dropped forcollection”,
“ns”:”foobar.map”,
“ok”:1
}
2. 如何查询mongoDB为我们提供的命令
2.1 在shell 中执行 db.listCommands()
2.2 访问网址API http://localhost:28017/_commands
//需要在启动项(mongodb.bat)配置—rest
mongod --dbpathD:\MongodbData --rest
//27017 + 1000 =28017
3. 常用命令举例
3.1查询服务器版本号和主机操作系统
db.runCommand({buildInfo:1}) //
3.2 查询执行集合的详细信息,大小,空间,索引等…
db.runCommand({collStats:”persons”})
3.3 查看操作本集合最后一次错误信息
db.runCommand({getLastError:”persons”})
十三. 固定集合特性
1. 概念:给集合指定大小,数量,增加一个,在未尾弹出一个(栈:先进后出)
2. 固定特性
2.1 固定集合默认是没有索引的,就算是_id也是没有索引的
2.2 由于不需分配新的空间,他插入的速度非常快
2.3 固定集合的顺序是确定的,导致查询速度也非常快
2.4 最适合的应用就是日志管理
3. 创建固定集合
3.1 创建一个新的固定集合,要求大小是100个字节,可以存储文档10个
db.createCollection(“mycoll”,{size:100,capped:true,max:10})
//mycoll 固定集合名称, capped封闭
3.2 把一个普通集合转换成固定集合
db.runCommand({converToCapped:”persons”,size:100000})
//persons要转换的集合
4. 反向排序,默认的插入顺序排序
4.1 查询固定集合mycoll并且反向排序
db.mycoll.find().sort({$natural:-1})
5. 尾部游标,可惜shell不支持, java和php等驱动是支持的
5.1 尾部游标概念: 这是个特殊的只能用到固定级的游标,它在没有结果的时候也不会自动销毁,直到结果的出现