MongoDB数据查询,分页,排序
2015-11-30 17:20
826 查看
MongoDB数据查询
数据准备:persons.jsonvar 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会将大的文档移动到集合后面,则这种情况会导致查询的数据有问题。如图:
相关文章推荐
- 分享微信开发Html5轻游戏中的几个坑
- 如何在 Fedora 上安装 MongoDB 服务器
- PHP添加yaf xhprof mongodb 同理
- mongodb安装
- 如何在 Ubuntu 上安装 MongoDB
- more、less 和 most 的区别
- 十万条Access数据表分页的两个解决方法
- PowerShell实现查询打开某个文件的默认应用程序
- perl操作MongoDB报错undefined symbol: HeUTF8解决方法
- asp下查询xml的实现代码
- SQL语句实现查询SQL Server服务器名称和IP地址
- SQL多表连接查询实例分析(详细图文)
- 有关数据库SQL递归查询在不同数据库中的实现方法
- sqlserver关于分页存储过程的优化【让数据库按我们的意思执行查询计划】
- 日常收集常用SQL查询语句大全
- 高效的mysql分页方法及原理
- asp又一个分页的代码例子
- SqlServer 2000、2005分页存储过程整理第1/3页
- sql 多表连接查询
- SQL查询出表、存储过程、触发器的创建时间和最后修改时间示例