数据准备: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;ilength;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({条件},{指定返回的键})
db.persons.find({},{name:1,age:1,country:1,_id:0})
db.persons.find({age:$gte:25,$lte:27}},_id:0,age:1,name:1})
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})
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})
db.person.update({country:”China”},{$set:{sex:”m”}})
db.persons.find({sex:{$in:[null]}},{country:1,name:1,_id:0})
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})
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;
}
}
}
}
}})
第一页: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)
...
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会将大的文档移动到集合后面,则这种情况会导致查询的数据有问题。如图: