七.   分页与排序

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 尾部游标概念: 这是个特殊的只能用到固定级的游标,它在没有结果的时候也不会自动销毁,直到结果的出现