首页 > DB > mongoDB > > 正文

mongoDB的分页和排序及游标-mongoDB的Find详解

发布人:zhoulujun@live.cn    点击:

在mongodb中,排序和索引其实都是十分容易的,先来小结下排序

关于索引 
   
  首先,mongodb的是B-tree的索引了。要注意的是,一个collection不能超过64个索引, 
索引的大小不能超过1024字节,其中包括字段名和值和命名空间。 
   首先照样创建数据: 
db.Indexing.insert( { name : "Denis", age : 20 } ) 

  首先,尝试看下mongodb的执行计划: 
db.Indexing.find({name: "Denis"}).explain(),这个是看当查找Denis的执行情况, 
结果如下: 
{"cursor" : "BtreeCursor name_1",
        "isMultiKey" : false,
        "n" : 1,
        "nscannedObjects" : 1,
        "nscanned" : 1,
        "nscannedObjectsAllPlans" : 1,
        "nscannedAllPlans" : 1,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "millis" : 1,
        "indexBounds" : {
        "name" : [
            [
                "Denis",
                "Denis"
            ]
        ]
    }, "server" : "Denis:27017"}
下面加个索引,如下: 
   db.Indexing.ensureIndex({name: 1}); 
  其中依然,1是升序,-1是降序,
 然后可以删除索引: 
  db.Indexing.dropIndex({name: 1}); 
  删除所有索引 
   
4 创建唯一索引 
   db.Indexing.ensureIndex({name: 1}, {unique: true}); 
  也就是加上{unique: true}就可以了 

5 创建复合索引 
   比如要创建name和age的复合索引,直接如下 
db.Indexing.ensureIndex({name: 1, age : 1}); 
  如果要复合唯一索引,则: 
   db.Indexing.ensureIndex({name: 1, age : 1}, {unique: true}) 

db.[documentName].find ({条件},{键指定})
 数据准备persons.json

 


    var persons = [{
        name:"jim",
        age:25,
        email:"75431457@qq.com",
        c:89,m:96,e:87,
        country:"USA",
        books:["JS","C++","EXTJS","MONGODB"]
    },
    {
        name:"tom",
        age:25,
        email:"214557457@qq.com",
        c:75,m:66,e:97,
        country:"USA",
        books:["PHP","JAVA","EXTJS","C++"]
    },
    {
        name:"lili",
        age:26,
        email:"344521457@qq.com",
        c:75,m:63,e:97,
        country:"USA",
        books:["JS","JAVA","C#","MONGODB"]
    },
    {
        name:"zhangsan",
        age:27,
        email:"2145567457@qq.com",
        c:89,m:86,e:67,
        country:"China",
        books:["JS","JAVA","EXTJS","MONGODB"]
    },
    {
        name:"lisi",
        age:26,
        email:"274521457@qq.com",
        c:53,m:96,e:83,
        country:"China",
        books:["JS","C#","PHP","MONGODB"]
    },
    {
        name:"wangwu",
        age:27,
        email:"65621457@qq.com",
        c:45,m:65,e:99,
        country:"China",
        books:["JS","JAVA","C++","MONGODB"]
    },
    {
        name:"zhaoliu",
        age:27,
        email:"214521457@qq.com",
        c:99,m:96,e:97,
        country:"China",
        books:["JS","JAVA","EXTJS","PHP"]
    },
    {
        name:"piaoyingjun",
        age:26,
        email:"piaoyingjun@uspcat.com",
        c:39,m:54,e:53,
        country:"Korea",
        books:["JS","C#","EXTJS","MONGODB"]
    },
    {
        name:"lizhenxian",
        age:27,
        email:"lizhenxian@uspcat.com",
        c:35,m:56,e:47,
        country:"Korea",
        books:["JS","JAVA","EXTJS","MONGODB"]
    },
    {
        name:"lixiaoli",
        age:21,
        email:"lixiaoli@uspcat.com",
        c:36,m:86,e:32,
        country:"Korea",
        books:["JS","JAVA","PHP","MONGODB"]
    },
    {
        name:"zhangsuying",
        age:22,
        email:"zhangsuying@uspcat.com",
        c:45,m:63,e:77,
        country:"Korea",
        books:["JS","JAVA","C#","MONGODB"]
    }];
    for(var i = 0;i
        db.persons.insert(persons[i])
        }

查询出所有数据的指定键(name ,age ,country)

    db.persons.find({},{name:1,age:1,country:1,_id:0})

2.查询条件

    592x264

    2.查询条件

    2.1查询出年龄在25到27岁之间的学生

    db.persons.find({age: {$gte:25,$lte:27},{_id:0,age:1})

    2.2查询出所有不是韩国籍的学生的数学成绩

    db.persons.find({country:{$ne:”Korea”}},{_id:0,m:1})

    3.包含或不包含

    $in或$nin

    2.3查询国籍是中国或美国的学生信息

    db.persons.find({country:{$in:[“USA”,“China”]}})

    2.4查询国籍不是中国或美国的学生信息

    db.persons.find({country:{$nin:[“USA”,“China”]}})

    4.OR查询

    $or

    2.4查询语文成绩大于85或者英语大于90的学生信息

    db.persons.find({$or:[{c:{$gte:85}},{e:{$gte:90}}]},{_id:0,c:1,e:1})

    5.Null

    把中国国籍的学生上增加新的键sex

    db.person.update({country:”China”},{$set:{sex:”m”}},false,true)

    2.5查询出sex 等于 null的学生

    db.persons.find({sex:{$in:[null]}},{country:1})

    6.正则查询

    2.6查询出名字中存在”li”的学生的信息

    db.persons.find({name:/li/i},{_id:0,name:1})

    7.$not的使用

    $not可以用到任何地方进行取反操作

    2.7查询出名字中不存在”li”的学生的信息

    db.persons.find({name:{$not:/li/i}},{_id:0,name:1})

    $not和$nin的区别是$not可以用在任何地方儿$nin是用到集合上的

    8.数组查询$all和index应用

    2.8查询喜欢看MONGOD和JS的学生

    db.persons.find({books:{$all:[“MONGOBD”,”JS”]}},{books:1,_id:0})

    2.9查询第二本书是JAVA的学习信息

    db.persons.find({“books.1”:”JAVA”})

    9.查询指定长度数组$size它不能与比较查询符一起使用(这是弊端)

    2.8查询出喜欢的书籍数量是4本的学生

    db.persons.find({books:{$size:4}},{_id:0,books:1})

    2.9查询出喜欢的书籍数量大于3本的学生

    1.增加字段size

    db.persons.update({},{$set:{size:4}},false,true)

    2.改变书籍的更新方式,每次增加书籍的时候size增加1

    db.persons.update({查询器},{$push:{books:”ORACLE”},$inc:{size:1}})

    3.利用$gt查询

    db.persons.find({size:{$gt:3}})

    2.10利用shell查询出Jim喜欢看的书的数量

    var persons = db.persons.find({name:"jim"})

    while(persons.hasNext()){

    bj = persons.next();

    print(obj.books.length)

    }

    课间小结

    1.mongodb 是NOSQL数据库但是他在文档查询上还是很强大的

    2.查询符基本是用到花括号里面的更新符基本是在外面

    3.shell是个彻彻底底的JS引擎,但是一些特殊的操作要靠他的

    各个驱动包来完成(JAVA,NODE.JS)

    10.$slice操作符返回文档中指定数组的内部值

    2.11查询出Jim书架中第2~4本书

    db.persons.find({name:"jim"},{books:{"$slice":[1,3]}})

    2.12查询出最后一本书

    db.persons.find({name:"jim"},{books:{"$slice":-1},_id:0,name:1})

    11.文档查询

    为jim添加学习简历文档 jim.json

    2.13查询出在K上过学的学生

    1. 这个我们用绝对匹配可以完成,但是有些问题(找找问题?顺序?总要带着score?)

    db.persons.find({school:{school:"K",score:"A"}},{_id:0,school:1})

    2.为了解决顺序的问题我可以用对象”.”的方式定位

    db.persons.find({"school.score":"A","school.school":"K"},{_id:0,school:1})

    3.这样也问题看例子:

    db.persons.find({"school.score":"A","school.school":”J”},{_id:0,school:1})

    同样能查出刚才那条数据,原因是score和school会去其他对象对比

    4.正确做法单条条件组查询$elemMatch

    db.persons.find({school:{$elemMatch:{school:"K",score:"A"}}})

    12.$where

    12.查询年龄大于22岁,喜欢看C++书,在K学校上过学的学生信息

    复杂的查询我们就可以用$where因为他是万能

    但是我们要尽量避免少使用它因为他会有性能的代价

    db.persons.find({"$where":function(){

    var books = this.books;

    var school = this.school;

    if(this.age > 22){

    var php = null;

    for ( var i = 0; i < books.length; i++) {

    if(books[i] == "C++"){

    php = books[i];

    if(school){

    for (var j = 0; j < school.length; j++) {

    if(school[j].school == "K"){

    return true;

    }

    }

    break;

    }

    }

    }

    }

    }})

    二、分页和排序

    1.Limit返回指定的数据条数

    1.1查询出persons文档中前5条数据

    db.persons.find({},{_id:0,name:1}).limit(5)

    2.Skip返回指定数据的跨度

    2.1查询出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,age:1}).sort({age:1})

    注意:mongodb的key可以存不同类型的数据排序就也有优先级

    最小值

    null

    数字

    字符串

    对象/文档

    数组

    二进制

    对象ID

    布尔

    日期

时间戳à正则 à最大值

 

    4.Limit和Skip完成分页

    4.1三条数据位一页进行分页

    第一页àdb.persons.find({},{_id:0,name:1}).limit(3).skip(0)

    第二页àdb.persons.find({},{_id:0,name:1}).limit(3).skip(3)

    4.2skip有性能问题,没有特殊情况下我们也可以换个思路

    对文档进行重新解构设计

    582x184

    每次查询操作的时候前后台传值全要把上次的最后一个文档的日期保存下来

    db.persons.find({date:{$gt:日期数值}}).limit(3)

    个人建议à应该把软件的中点放到便捷和精确查询上而不是分页的性能上

    因为用户最多不会翻查过2页的

    三、游标

    利用游标遍历查询数据

    var persons = db.persons.find();

    while(persons.hasNext()){

    bj = persons.next();

    print(obj.name)

    }

    593x245

    2.游标几个销毁条件

    1.客户端发来信息叫他销毁

    2.游标迭代完毕

    3.默认游标超过10分钟没用也会别清除

    3.查询快照

    快照后就会针对不变的集合进行游标运动了,看看使用方法.

    db.persons.find({$query:{name:”Jim”},$snapshot:true})

    高级查询选项

    $query

    $orderby

    $maxsan:integer最多扫描的文档数

    $min:doc 查询开始

    $max:doc 查询结束

    $hint:doc 使用哪个索引

    $explain:boolean 统计

    $snapshot:boolean一致快照

    613x383