您的位置:首页 > 数据库 > Mongodb

MongoDB数据查询,分页,排序

2015-11-30 17:20 826 查看

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)
}


指定返回的键

对于查询,我们知道使用
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:查询出年龄在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})




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数据分页

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)
...




其他分页

skip进行分页会有性能问题,效率不高,没有特殊要求的情况下,我们也可以换个思路进行分页。

如:我们可以对集合设计进行修正,给每个文档添加一个插入时间,若无特殊要求我们可以按照插入时间进行比较分页。

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


游标

利用游标遍历查询数据

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会将大的文档移动到集合后面,则这种情况会导致查询的数据有问题。如图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  mongodb 分页 查询