上一章学习了如何在MongoDB中进行数据库常规的CRUD操作,然而在数据库中还有一类非常重要的操作即查询,通过查询获取所需的文档数据。在MongoDB中查询操作通过find方法来进行,如下面的文档
{
“_id”:1.
“name”:”shihao”,
“age”:24
}假设该文档存在于集合users中,那么要查询到该文档只需简短的一行代码:>db.users.find({"name":"shihao"})即可。
find方法可以接受两个参数,第一个为查询条件,第二个为可选参数,可以限定find方法返回的内容。例如你只想得到上述文档中age的值,只需在第二个参数中指定age值为1即可。如下:

>db.users.find({"_id":1},{"age":1})

聪明的你可能已经想到如果不想得到某个键的信息,将其置为0即可:

>db.users.find({"_id":1},{"age":0})

关于查询条件
1、有几类常用的查询条件,lt(小于),lte(小于等于),gt(大于),gte(大于等于)
这类查询条件的使用非常简单,例如要查询年龄在24到30岁之间的人,也只需要下面一行代码即可:

>db.users.find({"age":{"$gte":24,"lte":30}})

显然这类查询条件很适合用来做时间方面的查询。
2、or查询。or查询只要有两类,一种是$in,可以用来匹配一个键的多个值,如要查询”name”值为数组[“joe”,”john”,”tom”]中的其中一个的文档,可以采用如下代码:

>db.users.find({"name":{"$in":["joe","john","tom"]}})

相对的存在nin可以过滤不满足条件的文档。第二种是or,用来查询匹配多个键值对条件的一个文档,如想要匹配”name”为”shihao”或”john”的文档,输入如下代码即可:

>db.users.find({"$or":[{"name":"shihao"},{"name":"john}]})

关于数组的查询
数组是一类特殊的数据结构,关于数组的查询主要有$all查询。例如含有以下两个数组的文档:
{“name”:[“joe”,”john”,”kobe”,”hardon”]}
{“name”:[“shihao”,”joe”,”john”,”tom”]}
要查询出所有name数组中含有”joe”,”john”的文档,

>db.users.find({"name":{"$all":["joe","john"]}})

此外,关于数组还有一类查询可以获取到指定长度的数组”$size”
例如:>db.user.find({"name":{"$size":3}})
前面已经说过find方法可以传入第二个参数,对于数组的查询,可以使用$slice指定返回的内容。
例如想要指定返回某博客中的最后10个评论,只需一行代码:

>db.blog.find(criteria,{"comments":{"$slice":-10}})

此外关于slice的应用需要提及的是slice可以指定两个参数,第一个是偏移量,第二个是计数值,例如想要获取从第24条评论开始之后的10条评论:

>db.blog.find(criteria,{"comments":{"$slice":[23,10]}})

如果知道数组的下标,使用slice非常有用,但是当不清楚下标,只了解数组中的某个属性值时,要指定返回该信息,可以使用定位符。

>db.blog.find({"comments.name":"joe"},{"comments.$":1})

关于嵌套文档的查询
例如如下文档
{
“_id”:1,
“age”:24,
“name”:{
“first”:”shi”,
“second”:”hao”
}
}
要根据嵌套的文档进行查询,使用.操作符即可,如:

>db.users.find({"name.first":"shi","name.second":"hao"})

关于游标
数据库使用游标来返回find查询得到的数据,通过给游标对象添加相应的方法可以设置返回文档的数目,略过多少信息,以及对查询到的文档进行排序操作。假设集合users中已经存在相应的文档数据,
启动mongo shell将find方法查询返回到一个游标cursor

>var cursor=db.users.find();

所谓游标,顾名思义就是一次可以返回一条结果,然后游标向右移动。
例如:

>while(cursor.hasNext()){
          var obj=cursor.next();
          }

hasNext()判断cursor是否有后续结果存在,若有就用cursor.next()返回。
此外可以给游标添加方法限制,且每个方法都会返回游标本身,这意味着可以形成方法链。

>var cursor=cursor.limit(50).skip(20).sort({"age":1})

limit(50)表示最多只能返回50条数据,skip(20)表示将会略过查询到的前20条数据,sort({“age”:1})表示按照年龄进行升序排列,若将”age”设置为-1则会进行降序排列。
值得注意的是在使用上述方法链的时候查询操作依然没有开始,游标赋值以及方法链都只是构造查询而已,当我们执行以下操作:

>cursor.hasNext()

查询才开始发往服务器,返回指定数据。
对于游标,需要提及的是在服务器端,游标是会消耗内存和其他资源的,游标遍历尽了结果以后,或者客户端发来消息要求终止,数据库都会释放这些资源,要尽量保证尽快释放游标。如果一个游标在10分钟内没有使用的话,数据库游标会自动销毁。