MongoDB数据查询,分页,排序

MongoDB数据查询

数据准备: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<persons.length;i++){
    db.persons.insert(persons[i])
}
var persons = db.persons.find({name:"jim"})
while(persons.hasNext()){
    obj = persons.next();
        print(obj.books.length)
} 
  1. 指定返回的键
    对于查询,我们知道使用db.[collectionName].find()是返回全部数据,返回某个文档的全部键值,但是,某些时候我们会希望返回固定的键对应的值,那么对于键指定,默认情况下,是会查询出id,因此如果不想查询出id或者某一列,添加id:0,这样,此列不会被查询出。
    语法:db.[collectionName].find({条件},{指定返回的键})
    例子:查询出所有的数据指定的键(name,age,country)
db.persons.find({},{name:1,age:1,country:1,_id:0})

这里写图片描述

  1. 查询条件
    首先看一下比较操作符:
    例1:查询出年龄在25到27岁之间的学生
db.persons.find({age:$gte:25,$lte:27}},_id:0,age:1,name:1})

这里写图片描述
例2:查询出所有不是韩国籍的学生的数学成绩

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

这里写图片描述
3. 包含或不包含
包含($in)和不包含($nin)类似关系型数据库中的in和not in,该操作只能操作在数组上。
例1:查询国籍是中国或美国的学生信息

 db.persons.find({country:{$in:["China","USA"]}},{name:1,_id:0,country:1})

这里写图片描述
例2:查询国籍不是中国或美国的学生信息

 db.persons.find({country:{$nin:["China","USA"]}},{name:1,_id:0,country:1})

这里写图片描述
4. OR查询
or查询即或者查询,or查询作用于数组。
例:查询语文成绩大于85或者英语大于90的学生信息

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

这里写图片描述

  1. Null
    首先数据修正:把中国国籍的学生上增加新的键ex,
    db.person.update({country:”China”},{$set:{sex:”m”}})
    这里写图片描述
    例:查询出sex 等于 null的学生
db.persons.find({sex:{$in:[null]}},{country:1,name:1,_id:0})

这里写图片描述
6. 正则查询
例:查询出名字中存在”li”的学生的信息

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

这里写图片描述
7. $not的查询
$not可以用到任何地方进行取反操作。
例:查询出名字中不存在”li”的学生的信息

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

这里写图片描述
8. 数组查询$all和index的应用
例:查询喜欢看MONGOD和JS的学生

db.persons.find({books:{$all:["MONGODB","JS"]}},{books:1,_id:0})

这里写图片描述
例:查询第二本书是JAVA的学习信息

db.persons.find({"books.1":"JAVA"},{_id:0,name:1,books:1})

这里写图片描述

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

例子:查询出喜欢的书籍数量是4本的学生

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

这里写图片描述
例:查询出喜欢的书籍数量大于3本的学生
这种情况下,由于size不能进行比较,则无法进行操作,解决方法可以修改文档结构,添加size键来记载书籍数量再进行比较查询。

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

var persons = db.persons.find({name:"jim"})
while(persons.hasNext()){
    obj = persons.next();
        print(obj.books.length)
} 

10 . $slice操作符返回文档中指定数组的内部值
例:查询出Jim书架中第2~4本书

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

这里写图片描述
例:查询出最后一本书

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

这里写图片描述
11. 文档查询
为jim添加学习简历文档 jim.json

var jim = [{
    school :"K",
    score:"A"
},{
    school :"L",
    score:"B"
},{
    school :"J",
    score:"A+"
}]
db.persons.update({name:"jim"},{$set:{school:jim}})

这里写图片描述

例:查询出在K上过学的学生
正常情况下,我们会进行如下查询:

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

但是这种情况下无法查询到数据:
这里写图片描述
由于scholl是一个文档,所以我们应该使用文档匹配,如下:

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

查询结果如下:
这里写图片描述
但是这种匹配方式,我们总要匹配Document中的全部信息,比如我的查询条件不需要score,但是依旧要写,那么来看下面的方式解决这个问题:

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

查询结果:
这里写图片描述

但是这种查询,会出现如下问题:
查询在J学校上课,成绩为A的学生信息:

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

这里写图片描述

很明显,该数据并不存在,但是依旧查询出结果,因此此种方式有一定问题。
正确做法是使用单条条件组查询$elemMatch

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

这里写图片描述
而:

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

这里写图片描述
12 . $where
复杂的查询我们就可以用$where,因为$where是万能,但是我们要尽量避免少使用它,因为使用$where会有性能的代价。
例:查询年龄大于22岁,喜欢看C++书,在K学校上过学的学生信息

db.persons.find({"$where":function(){
    //得到查询结果的每一条文档
    var books = this.books;
    //得到文档中的school对象
    var school = this.school;
    //如果年纪>=22
    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++) {
                        //判断是不是在K上学
                        if(school[j].school == "K"){
                            //返回是真
                            return true;
                        }
                    }
                    break;
                }
            }
        }   
    }
}})

这里写图片描述

MongoDB数据分页

  1. limit和skip完成分页
    limit类似于mysql中的limit,限制查询条数
    skip为跨过多少条进行查询。
    例:三条数据位一页进行分页
第一页:db.persons.find({},{_id:0,name:1,books:1}).limit(3).skip(0)
第二页:db.persons.find({},{_id:0,name:1,books:1}).limit(3).skip(3)
...

这里写图片描述

  1. 其他分页
    skip进行分页会有性能问题,效率不高,没有特殊要求的情况下,我们也可以换个思路进行分页。
    如:我们可以对集合设计进行修正,给每个文档添加一个插入时间,若无特殊要求我们可以按照插入时间进行比较分页。
db.persons.find({date:{$gt:日期数值}}).limit(3)

游标

  1. 利用游标遍历查询数据
    var  persons = db.persons.find();
    while(persons.hasNext()){
        obj = persons.next();
          print(obj.name)
     } 

这里写图片描述
游标查询:
这里写图片描述
游标查询是以此移动指针,当游标移动到最后位置,则不能回到初始位置,因此游标只能查询一次,一次之后就不能查询到数据。
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 一致快照 

4. .为什么有的时候要用查询快照?
因为有时候查询之后,我们对数据进行了修改,如添加很大数据,超过了文档的预留内存,此时MongoDB会将大的文档移动到集合后面,则这种情况会导致查询的数据有问题。如图:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值