超越之MongDB系列教程(六) MongDB的查询

查询条件:db.docName.find({条件},{键指定})
< : $lt(less then)  
> : $gt(grent then) 
<=: $lte(less then equals)
>=: $gte(grent the equals)
!=: $ne(not equals)

例:{age:{$gte:22,$lte:27}}

0.准备测试数据
var persons = [{
name:"jim",
age:25,
email:"[email protected]",
c:89,m:96,e:87,
country:"USA",
books:["JS","C++","EXTJS","MONGODB"]
},
{
name:"tom",
age:25,
email:"[email protected]",
c:75,m:66,e:97,
country:"USA",
books:["PHP","JAVA","EXTJS","C++"]
},
{
name:"lili",
age:26,
email:"[email protected]",
c:75,m:63,e:97,
country:"USA",
books:["JS","JAVA","C#","MONGODB"]
},
{
name:"zhangsan",
age:27,
email:"[email protected]",
c:89,m:86,e:67,
country:"China",
books:["JS","JAVA","EXTJS","MONGODB"]
},
{
name:"lisi",
age:26,
email:"[email protected]",
c:53,m:96,e:83,
country:"China",
books:["JS","C#","PHP","MONGODB"]
},
{
name:"wangwu",
age:27,
email:"[email protected]",
c:45,m:65,e:99,
country:"China",
books:["JS","JAVA","C++","MONGODB"]
},
{
name:"zhaoliu",
age:27,
email:"[email protected]",
c:99,m:96,e:97,
country:"China",
books:["JS","JAVA","EXTJS","PHP"]
},
{
name:"piaoyingjun",
age:26,
email:"[email protected]",
c:39,m:54,e:53,
country:"Korea",
books:["JS","C#","EXTJS","MONGODB"]
},
{
name:"lizhenxian",
age:27,
email:"[email protected]",
c:35,m:56,e:47,
country:"Korea",
books:["JS","JAVA","EXTJS","MONGODB"]
},
{
name:"lixiaoli",
age:21,
email:"[email protected]",
c:36,m:86,e:32,
country:"Korea",
books:["JS","JAVA","PHP","MONGODB"]
},
{
name:"zhangsuying",
age:22,
email:"[email protected]",
c:45,m:63,e:77,
country:"Korea",
books:["JS","JAVA","C#","MONGODB"]
}]
for(var i = 0;i db.persons.insert(persons[i])
}
var persons = db.persons.find({name:"jim"})
while(persons.hasNext()){
obj = persons.next();
        print(obj.books.length)


查询示例:
1.指定返回的键
1)查询出所有数据的指定的字段(name,age,email)
> db.persons.find({},{_id:0,name:1,age:1,email:1})
{ "name" : "jim", "age" : 25, "email" : "[email protected]" }
{ "name" : "tom", "age" : 25, "email" : "[email protected]" }
{ "name" : "lili", "age" : 26, "email" : "[email protected]" }
{ "name" : "zhangsan", "age" : 27, "email" : "[email protected]" }
{ "name" : "lisi", "age" : 26, "email" : "[email protected]" }
{ "name" : "wangwu", "age" : 27, "email" : "[email protected]" }
{ "name" : "zhaoliu", "age" : 27, "email" : "[email protected]" }
{ "name" : "piaoyingjun", "age" : 26, "email" : "[email protected]" }
{ "name" : "lizhenxian", "age" : 27, "email" : "[email protected]" }
{ "name" : "lixiaoli", "age" : 21, "email" : "[email protected]" }
{ "name" : "zhangsuying", "age" : 22, "email" : "[email protected]" }

2.查询条件
1)查询年龄在25到27岁之间的学生(AND)
> db.persons.find({age:{$gte:25,$lte:27}},{_id:0,name:1,age:1})
{ "name" : "jim", "age" : 25 }
{ "name" : "tom", "age" : 25 }
{ "name" : "lili", "age" : 26 }
{ "name" : "zhangsan", "age" : 27 }
{ "name" : "lisi", "age" : 26 }
{ "name" : "wangwu", "age" : 27 }
{ "name" : "zhaoliu", "age" : 27 }
{ "name" : "piaoyingjun", "age" : 26 }
{ "name" : "lizhenxian", "age" : 27 }

2)查询出所有不是韩国国籍的学生数学成绩
> db.persons.find({country:{$ne:"Korea"}},{_id:0,name:1,country:1,age:1})
{ "name" : "jim", "age" : 25, "country" : "USA" }
{ "name" : "tom", "age" : 25, "country" : "USA" }
{ "name" : "lili", "age" : 26, "country" : "USA" }
{ "name" : "zhangsan", "age" : 27, "country" : "China" }
{ "name" : "lisi", "age" : 26, "country" : "China" }
{ "name" : "wangwu", "age" : 27, "country" : "China" }
{ "name" : "zhaoliu", "age" : 27, "country" : "China" }

3.包含或不包含$in或$nin(只能用于数组)
1)查询国籍是中国或美国的学生信息
> db.persons.find({country:{$in:["USA","China"]}},{_id:0,name:1,country:1,age:1})
{ "name" : "jim", "age" : 25, "country" : "USA" }
{ "name" : "tom", "age" : 25, "country" : "USA" }
{ "name" : "lili", "age" : 26, "country" : "USA" }
{ "name" : "zhangsan", "age" : 27, "country" : "China" }
{ "name" : "lisi", "age" : 26, "country" : "China" }
{ "name" : "wangwu", "age" : 27, "country" : "China" }
{ "name" : "zhaoliu", "age" : 27, "country" : "China" }

2)查询国籍不是中国美国的学生信息
> db.persons.find({country:{$nin:["USA","China"]}},{_id:0,name:1,country:1,age:1})
{ "name" : "piaoyingjun", "age" : 26, "country" : "Korea" }
{ "name" : "lizhenxian", "age" : 27, "country" : "Korea" }
{ "name" : "lixiaoli", "age" : 21, "country" : "Korea" }
{ "name" : "zhangsuying", "age" : 22, "country" : "Korea" }

4.或查询$or
1)查询国籍是中国或美国的学生信息
> db.persons.find({$or:[{country:"USA"},{country:"China"}]},{_id:0,name:1,country:1,age:1})
{ "name" : "jim", "age" : 25, "country" : "USA" }
{ "name" : "tom", "age" : 25, "country" : "USA" }
{ "name" : "lili", "age" : 26, "country" : "USA" }
{ "name" : "zhangsan", "age" : 27, "country" : "China" }
{ "name" : "lisi", "age" : 26, "country" : "China" }
{ "name" : "wangwu", "age" : 27, "country" : "China" }
{ "name" : "zhaoliu", "age" : 27, "country" : "China" }

5.NULL值的记录查询
1)把中国国籍的学生上增加新的键sex
> db.persons.update({country:"China"},{$set:{sex:"M"}},false,true)
> db.persons.find({},{_id:0,name:1,age:1,country:1,sex:1});
{ "name" : "jim", "age" : 25, "country" : "USA" }
{ "name" : "tom", "age" : 25, "country" : "USA" }
{ "name" : "lili", "age" : 26, "country" : "USA" }
{ "name" : "piaoyingjun", "age" :26, "country" : "Korea" }
{ "name" : "lizhenxian", "age" : 27, "country" : "Korea" }
{ "name" : "lixiaoli", "age" : 21, "country" : "Korea" }
{ "name" : "zhangsuying", "age" :22, "country" : "Korea" }
{ "age" : 27, "country" : "China", "name" : "zhangsan", "sex" : "M" }
{ "age" : 26, "country" : "China", "name" : "lisi", "sex" : "M" }
{ "age" : 27, "country" : "China", "name" : "wangwu", "sex" : "M" }
{ "age" : 27, "country" : "China", "name" : "zhaoliu", "sex" : "M" }

2)查询出sex等于null的学生(只有中国学生有性别)
> db.persons.find({sex:{$in:[null]}},{_id:0,name:1,age:1,country:1,sex:1});
{ "name" : "jim", "age" : 25, "country" : "USA" }
{ "name" : "tom", "age" : 25, "country" : "USA" }
{ "name" : "lili", "age" : 26, "country" : "USA" }
{ "name" : "piaoyingjun", "age" : 26, "country" : "Korea" }
{ "name" : "lizhenxian", "age" : 27, "country" : "Korea" }
{ "name" : "lixiaoli", "age" : 21, "country" : "Korea" }
{ "name" : "zhangsuying", "age" : 22, "country" : "Korea" }

6.正则查询
1)查询出名字中存在"li"的学生信息
> db.persons.find({name:/li/i},{_id:0,name:1})
{ "name" : "lili" }
{ "name" : "lizhenxian" }
{ "name" : "lixiaoli" }
{ "name" : "lisi" }
{ "name" : "zhaoliu" }

7.$not的使用 $not可以用到任何地方进行取反操作
1)$not与$nin的区别是$not可以用在任何地方$nin是用到数组集合上的
查询出名字中不存在"li"的学生的信息
> db.persons.find({name:{$not:/li/i}},{_id:0,name:1})
{ "name" : "jim" }
{ "name" : "tom" }
{ "name" : "zhangsan" }
{ "name" : "piaoyingjun" }
{ "name" : "zhangsuying" }
{ "name" : "wangwu" }

8.数组查询$all和index应用
1)查询喜欢看Mongodb和JS的学生
> db.persons.find({books:{$all:["JS","MONGODB"]}},{_id:0,name:1,books:1})
{ "name" : "jim", "books" : [  "JS",  "C++",  "EXTJS",  "MONGODB" ] }
{ "name" : "lili", "books" : [  "JS",  "JAVA",  "C#",  "MONGODB" ] }
{ "books" : [  "JS",  "JAVA",  "EXTJS",  "MONGODB" ], "name" : "zhangsan" }
{ "name" : "piaoyingjun", "books" : [  "JS",  "C#",  "EXTJS",  "MONGODB" ] }
{ "name" : "lizhenxian", "books" : [  "JS",  "JAVA",  "EXTJS",  "MONGODB" ] }
{ "name" : "lixiaoli", "books" : [  "JS",  "JAVA",  "PHP",  "MONGODB" ] }
{ "name" : "zhangsuying", "books" : [  "JS",  "JAVA",  "C#",  "MONGODB" ] }
{ "books" : [  "JS",  "C#",  "PHP",  "MONGODB" ], "name" : "lisi" }
{ "books" : [  "JS",  "JAVA",  "C++",  "MONGODB" ], "name" : "wangwu" }

2)查询第二本书是JAVA的学生信息
> db.persons.find({"books.1":"JAVA"},{_id:0,name:1,books:1})
{ "name" : "tom", "books" : [  "PHP",  "JAVA",  "EXTJS",  "C++" ] }
{ "name" : "lili", "books" : [  "JS",  "JAVA",  "C#",  "MONGODB" ] }
{ "books" : [  "JS",  "JAVA",  "EXTJS",  "MONGODB" ], "name" : "zhangsan" }
{ "name" : "lizhenxian", "books" : [  "JS",  "JAVA",  "EXTJS",  "MONGODB" ] }
{ "name" : "lixiaoli", "books" : [  "JS",  "JAVA",  "PHP",  "MONGODB" ] }
{ "name" : "zhangsuying", "books" : [  "JS",  "JAVA",  "C#",  "MONGODB" ] }
{ "books" : [  "JS",  "JAVA",  "C++",  "MONGODB" ], "name" : "wangwu" }
{ "books" : [  "JS",  "JAVA",  "EXTJS",  "PHP" ], "name" : "zhaoliu" }

9.查询指定长度数组$size它不能与比较查询符一起使用(这是弊端)
1)查询出喜欢的书籍数量是4本的学生
> db.persons.find({books:{$size:4}},{_id:0,name:1,books:1})
{ "name" : "jim", "books" : [  "JS",  "C++",  "EXTJS",  "MONGODB" ] }
{ "name" : "tom", "books" : [  "PHP",  "JAVA",  "EXTJS",  "C++" ] }
{ "name" : "lili", "books" : [  "JS",  "JAVA",  "C#",  "MONGODB" ] }
{ "books" : [  "JS",  "JAVA",  "EXTJS",  "MONGODB" ], "name" : "zhangsan" }
{ "name" : "piaoyingjun", "books" : [  "JS",  "C#",  "EXTJS",  "MONGODB" ] }
{ "name" : "lizhenxian", "books" : [  "JS",  "JAVA",  "EXTJS",  "MONGODB" ] }
{ "name" : "lixiaoli", "books" : [  "JS",  "JAVA",  "PHP",  "MONGODB" ] }
{ "name" : "zhangsuying", "books" : [  "JS",  "JAVA",  "C#",  "MONGODB" ] }
{ "books" : [  "JS",  "C#",  "PHP",  "MONGODB" ], "name" : "lisi" }
{ "books" : [  "JS",  "JAVA",  "C++",  "MONGODB" ], "name" : "wangwu" }
{ "books" : [  "JS",  "JAVA",  "EXTJS",  "PHP" ], "name" : "zhaoliu" }

2)查询出喜欢的书籍数量大于5本的学生
> db.persons.update({},{$set:{size:4}},false,true) #增加字段size
> db.persons.update({name:"jim"},{$push:{books:"ORACLE"},$inc:{size:1}}) #改变书籍的更新方式,每次增加书籍的时候size增加1
> db.persons.find({},{_id:0,name:1,books:1,size:1})
{ "books" : [  "PHP",  "JAVA",  "EXTJS",  "C++" ], "name" : "tom", "size" : 4 }
{ "books" : [  "JS",  "JAVA",  "C#",  "MONGODB" ], "name" : "lili", "size" : 4 }
{ "books" : [  "JS",  "JAVA",  "EXTJS",  "MONGODB" ], "name" : "zhangsan", "size" : 4 }
{ "books" : [  "JS",  "C#",  "EXTJS",  "MONGODB" ], "name" : "piaoyingjun", "size" : 4 }
{ "books" : [  "JS",  "JAVA",  "EXTJS",  "MONGODB" ], "name" : "lizhenxian", "size" : 4 }
{ "books" : [  "JS",  "JAVA",  "PHP",  "MONGODB" ], "name" : "lixiaoli", "size": 4 }
{ "books" : [  "JS",  "JAVA",  "C#",  "MONGODB" ], "name" : "zhangsuying", "size" : 4 }
{ "books" : [  "JS",  "C#",  "PHP",  "MONGODB" ], "name" : "lisi", "size" : 4 }
{ "books" : [  "JS",  "JAVA",  "C++",  "MONGODB" ], "name" : "wangwu", "size" :4 }
{ "books" : [  "JS",  "JAVA",  "EXTJS",  "PHP" ], "name" : "zhaoliu", "size" : 4 }
{ "books" : [  "JS",  "C++",  "EXTJS",  "MONGODB",  "ORACLE" ], "name" : "jim","size" : 5 }
 
3)查询书籍大于4本的学生
> db.persons.find({size:{$gt:4}},{_id:0,name:1})
{ "name" : "jim" }

4)利用shell查询出Jim喜欢看的书的数量(用游标实现的)
var persons = db.persons.find({name:"jim"})
while(persons.hasNext()){
   obj = persons.next();
   print(obj.books.length);
}

10.返回文档中指定数组的内部值$slice
1)查询出jim书架中第2-4本书
> db.persons.find({name:"jim"},{_id:0,books:{"$slice":[1,3]}})
{ "_id" : ObjectId("52e643af06277e7d6c6ab516"), "age" : 25, "books" : [  "C++", "EXTJS",  "MONGODB" ], 
"c" : 89, "country" : "USA", "e" : 87, "email" : "[email protected]", "m" : 96, "name" : "jim", "size" : 5 }

2)查询出最后一本书
> db.persons.find({name:"jim"},{books:{"$slice":-1},_id:0})
{ "age" : 25, "books" : [  "ORACLE" ], "c" : 89, "country" : "USA", "e" : 87,
 "email" : "[email protected]", "m" : 96, "name" : "jim", "size" : 5 }

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


1)查询出在k上过学的学生

1.这个我们用绝对匹配可以完成,但是有些问题(总要带着score)
> db.persons.find({school:{school:"K",score:"A"}},{_id:0,school:1})
{ "school" : [{"school" : "K","score" : "A" }, {"school" : "L","score":"B" }, {"school":"J","score" : "A+"}]}

2.为了解决顺序问题我们可以用对象“.”的方式定位(注意:用[对象.属性]的方式加双引号)
> db.persons.find({"school.school":"K"},{_id:0,school:1})
{ "school" : [{"school" : "K","score" : "A" },{"school" : "L","score" : "B" },{"school" : "J","score":"A+"}]}
3.错误的查询结果:
查询成绩为A,学校为J,其实记录不存在,但可以查出结果
> db.persons.find({"school.score":"A","school.school":"J"},{_id:0,school:1})
{ "school" : [{"school" : "K","score" : "A" }, {"school" : "L","score" : "B" },{"school" : "J","score" : "A+" } ] }
以上同样可以查出刚才那条数据,原因是score和school会去其它对象中查找
正确的查询看第4条
  
4.组合条件查询$elemMatch(正确的做法单个条件组查询)
> db.persons.find({school:{$elemMatch:{school:"K",score:"A"}}},{_id:0,email:0,cuntry:0,e:0,m:0,score:0,size:0,age:0})
{ "books" : [  "JS",  "C++",  "EXTJS",  "MONGODB",  "ORACLE" ],
  "c" : 89, 
  "name : "jim", 
  "school" : [  { "school" : "K", "score" : "A" },{"school" : "L","score" : "B" },
                { "school" : "J", "score" : "A+" } 
             ] 
}

5.复杂查询用$where(比较耗费资源)
1)查询年龄大于22岁,喜欢看C++书,在K学校上过学的学生信息 
db.persons.find({"$where":function(){
    var books = this.books;//得到查询结果的每一条文档
    var school = this.school;//得到文档中的school对象
    if(this.age > 22){ //如果年纪>=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;
            }
        }
    }
  }
}})

7.查询指定数据条数limit,查询前5条记录
> db.persons.find({},{_id:0,name:1}).limit(5)
{ "name" : "tom" }
{ "name" : "lili" }
{ "name" : "zhangsan" }
{ "name" : "piaoyingjun" }
{ "name" : "lizhenxian" }

8.查询指定数据的跨度skip,从第4条开始取5条记录
> db.persons.find({},{_id:0,name:1}).limit(5).skip(4)
{ "name" : "lizhenxian" }
{ "name" : "lixiaoli" }
{ "name" : "zhangsuying" }
{ "name" : "lisi" }
{ "name" : "wangwu" }

9.查询按照年龄排序的数据[1,-1] sort
按age正序排序
> db.persons.find({},{_id:0,name:1,age:1}).sort({age:1})
{ "age" : 21, "name" : "lixiaoli" }
{ "age" : 22, "name" : "zhangsuying" }
{ "age" : 25, "name" : "tom" }
{ "age" : 25, "name" : "jim" }
{ "age" : 26, "name" : "lili" }
{ "age" : 26, "name" : "piaoyingjun" }
{ "age" : 26, "name" : "lisi" }
{ "age" : 27, "name" : "zhangsan" }
{ "age" : 27, "name" : "lizhenxian" }
{ "age" : 27, "name" : "wangwu" }
{ "age" : 27, "name" : "zhaoliu" }

按age倒序排序
> db.persons.find({},{_id:0,name:1,age:1}).sort({age:-1})
{ "age" : 27, "name" : "zhangsan" }
{ "age" : 27, "name" : "lizhenxian" }
{ "age" : 27, "name" : "wangwu" }
{ "age" : 27, "name" : "zhaoliu" }
{ "age" : 26, "name" : "lili" }
{ "age" : 26, "name" : "piaoyingjun" }
{ "age" : 26, "name" : "lisi" }
{ "age" : 25, "name" : "tom" }
{ "age" : 25, "name" : "jim" }
{ "age" : 22, "name" : "zhangsuying" }
{ "age" : 21, "name" : "lixiaoli" }

10.用limit和skip完成分页
1)3条记录一页进行分页
第一页:db.persons.find({},{_id:0,name:1}).limit(3).skip(0)
第二页:db.persons.find({},{_id:0,name:1}).limit(3).skip(3)

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

表结构如下:
_id name age date
001 jim 25 2014-2-1 11:57:31
002 tom 35 2014-2-2 11:57:31
003 lili 21 2014-2-3 11:57:31
004 zhang 23 2014-2-4 11:57:31
005 wang 26 2014-2-5 11:57:31

每次查询操作时,将时间作为条件
db.persons.find({date:{$gt:日期数值}}).limit(3)
 
11.游标操作
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 一致快照 


================================================

原文:http://blog.csdn.net/cyjch/article/details/51767861
作者:超越
超越的主页:http://blog.csdn.net/cyjch

================================================





你可能感兴趣的:(数据库)