《MongoDB权威指南》学习整理----MongoDB文档查询

来源:互联网 发布:mysql使用 编辑:程序博客网 时间:2024/05/22 12:35

简介

MongoDB中的查询使用db.collection.find/findOne()函数来完成。find函数返回包含0-n个文档的查询目标集合的子集合。

使用方法:

db.collection.find(query,fields,limit,skip,batchSize,options)

db.collection.findOne(query,fields,options)

参数说明:

query:

查询参数文档,文档中的多个key-value是以and的形式组合的,也就是查询条件是query中的key1=value1 and key2=value2 …。当query不存在或者为"{}"的时候默认返回整个查询目标集合。query文档对象中的value在传递给mongoDB的时候必须是常量。mongoDB不能解析/计算传递给它的查询文档中的value的变量。query文档中的key-value是按声明顺序执行的,所以可以根据不同的情况优化key-value的顺序。同时,queryDocObj中是可以将正则表达式(符合Perl标准)作为key的value来匹配条件。

比较条件句:

查询参数文档,不仅可以通过":"来作为等于的效果。也可以通过使用比较操作符来实现范围查找。mongoDB中的条件句比较操作符有:

$lt,lessthan,小于;$lte,lessthanequals,小于等于;$gt,greatthan,大于;$gte,greatthanequals,大于等于;$ne,notequals,不等于。

使用方式:{key:{比较运算符:value}}

OR条件句:

默认情况下,query文档中的key-value都是AND关系的。如果需要OR查询怎么处理呢。mongoDB提供了'$or'和'$in'条件句来进行or的查询,同一key的不同value的or关系使用'$in',$in后边的value必须是数组,即使只有一个元素:

find({key:{'$in':[value1,value2,value3…]}})

$nin==notin,与$in是相反关系,使用方式与'$in'相同。

如果是多个不同的key的or关系使用'$or':

find({'$or':[{key1:value1},{key2:value2}]})

NOT条件句:

$not是元条件句,可以用于任何的query文档对象之前,表示相反。例如:

find({'$not',{queryDocObj}})

query对象中的null

在mongoDB中,null是一种特殊的数据类型,所以它完全可以匹配集合中key值为null的文档。但是不仅仅如此,null也会匹配到没有该key值的文档对象。所以在使用null查询的时候一定要确定是要查询key的值为null的文档还是要查询key值不存在的文档。

如果查询key值为null且无key值的文档,那么直接使用{key:null}即可。

如果只查询key值为null,不要key值不存在的文档,那么需要使用$exist条件句,保证key存在:{key:{"$in":[null],'$exist':true}}

数组查询

数组值查询

当需要查询文档中的某个value为数组类型数据的时候,如果以一个元素值为限定条件可以直接使用:

find({key:数组某元素值})

如果以多个元素为限定,即目标数组中必须包含多个元素,就需要使用到$all条件句,$all条件句中的元素顺序不重要:

find({key:{'$all':[限定元素1,限定元素2….]}})

如果要查询指定位置的元素的值,可是使用下标(从0开始)的方式:

find({key.下标值:值})

数组长度查询

mongoDB为我们不仅为我们提供了基于数组中元素值的查询,也为我们提供了数组长度的查询。通过使用$size条件句,可实现数组长度为筛选条件的查询:

find{key:{'$size':目标长度}}

如果要查询长度范围,我们可能希望结合前边提到的$gt等比较条件句:

find{key:{'$size':{'$gt':3}}}

可惜在mongoDB并不支持这么使用,这么查询不会有结果。变通的条件是我们为文档对象添加一个key为size,value为数组长度的键值对。不过这么做我们必须保证每次对数组元素增减的时候同步更新size的值。例如

update({'$push':{key:'aaa'},'$inc':{'size':1}})或update({'$pop':{key:1},'$inc':{'size':-1}})

数组元素的返回值个数

当我们查询数组的时候,可能会限定数组元素的返回值个数,那么我们就需要用到$slice条件句,该条件句主要是为了限定返回的数组中元素的个数或元素的范围,默认情况下返回数组所在文档中的所有key。尤其要注意的是,该条件句是在find函数的第二个参数位置处使用。例如:

返回从前数n个元素:

find(queryDocObj,{数组key:{'$slice':n}}

返回从后数n个元素:

find(queryDocObj,{数组key:{'$slice':-n}})

通过偏移量来限定返回的元素范围:

find{queryDocObj,{数组key:{'$slice':[偏移量,个数]}}}

内嵌文档查询

对于内嵌文档查询,根据过滤条件分为两种情况:

根据某个条件过滤:

根据某单个条件过滤,比较简单,使用key.子文档key就可以,所以说文档中的key命名不能有".":find({key.subKey:value})即可以查询。

根据某几个条件过滤

当根据多个条件过滤时,我们必须保证多个过滤条件存在于一个内嵌文档中,那么就需要mongoDB中的$elemMatch条件句为我们保证我们提供的条件存在于一个内嵌文档中。

find({内嵌文档key:{'$elemMatch':{内嵌文档中的key1:value1,内嵌文档中key2:value2…}}})

复杂查询

上边提到的查询都是通过从外部给定某些条件来进行数据查询,如果以上介绍的方式无法查询的时候,就需要用到mongoDB为我们提供的$where条件句了。$where条件句最强大的功能是可以将JS函数作为过滤条件进行查询,这种方式几乎可以做到任何查询。但是要知道的,使用$where查询的速度较慢,而且不能使用索引,这要是因为使用$where时,BSON格式的数据转化为JS对象,然后才通过$where来运行,尽量不使用$where或将$where在常规查询之后

$where例子:

find({'$where':function(){

for(var current in this){

for(var other in this){

if(current!=other&&this[current]==this[other]){

return true;

}

}

}

return false;

}})

上边的例子中this代表了集合中某个文档,current和other都是代表了文档中key/value,在JS中this[current]==this.current所以上边这个查询就是要查询key不同而value相同的那部分文档。

 

fields:

指定返回键参数,可以指定或者剔除某些key,但是_id这个key是无法指定或提出的。指定:{keyName:1}。剔除:{keyName:0}。当keyName的value值为1,那么就是指定该key作为结果文档中的一部分,如果value为0就是指结果文档中不包括该keyName。fields不存在或使用'{}'时,表示返回默认key,即全部的key

 

limit:

类似于mysql中的limit相似,都是要指明显示多少条记录,不要的时候使用{}来代表。不过这里只能是一个数字,配合下一个skip参数使用达到Mysql中的limit skip,num的效果。例如:

find({},{},3)

就是查询集合中所有文档中的前3个,返回所有key-value。

 

skip:

与mysql中的offset相同,指明了返回的集合中第一个文档的偏移量。当偏移量过多的时候会降低性能,可以通过添加查询项(大于某个值)等方式减少偏移量。例如:

find({},{},{},4)

就是查询集合中从第5个开始(偏移4个文档)的所有文档,返回所有key-value。

 

游标:

MongoDB中的游标概念与传统的关系型数据库中游标的概念相似,都是指代查询的结果集一个缓存空间,同时使用游标位置来定位当前游标指向的某条记录/文档。

在MongoDB中,find的返回值赋给的游标对象支持hasNext()来判断是否有下一个文档,或forEach(function(doc){})的迭代器方式遍历。

服务器端的游标会占用服务器内存等资源,所以当游标使用完会自动销毁。或者当创建的游标10分钟不使用,服务器端也会自动的将该游标销毁。

 

查询结果排序

mongoDB提供了sort方法对结果集(游标)排序,排序参数是一个文档,可以按多个key排序。value值为1则为升序,-1为降序:

find().sort({key1:1,key2:-1})

 

mongoDB高级查询

所谓的高级查询,实际上就是对查询的结果进行更详细的设置。所以说高级==详细(个人拙见)。例如上边的提到的排序就是高级查询的一种,虽然从形式上我们是通过sort()方法实现的,但实质上MongoDB将其转发为了:find({'$query':queryDocObj,'$orderby':{key:1/-1}})

当然,高级查询肯定不可能单指排序,还有如下的查询选项,使用方式都和上边转化后的形式一样:

$maxscan:integer

指定查询最多扫描的文档数,最多从多少个文档中查询。

$min:document

查询开始的条件

$max:document

查询结束的条件

$hint:document

指定使用哪个索引进行查询

$explain:boolean

得到查询执行的细节(用到的索引,结果数量,耗时等)

$snapshot:boolean

确保查询的结果是在查询那一刻的一致快照。就是保证在整个查询周期中,不因为执行了insert、update等操作造成查询结果的不一致。

 

条件句与修改器的概念及区别

本文中多次提到了,类似于$not,$lt,$or这样的条件句,他们的结构和上一篇blog中介绍的update中$set,$pop等修改器一样。那么他们有什么区别呢。首先,用在查询中的叫条件句,用在更新中的叫修改器。其次,条件句是内层文档的key,而修改器是外层文档的key。例如:

修改器{'$set':{key:value}}

条件句${key:{'$lt':value}}

最后,一个key可以对应多个条件句,但是只能对应一个修改器。

0 0