(1)限定返回结果条数和字段
MongoDB提供了 limit 限制返回的条数,并 find 查询时可以设置参数限制只返回哪些字段。
我们在开发过程中如果每次都返回所有文档和所有字段会比较慢,合理地限制返回条数以及只返回需要的字段可以很大程度地提高性能,尤其是单个文档比较大的情况下。
(2)避免使用 skip 跳过大量结果
skip 一般与limit配合使用做分页,用 skip 跳过少量的文档是没有问题的。但是,如果文档数量非常多的话,skip就会变得很慢。因为skip会一条一条跳过数据,所以跳过的数据也是需要加载到内存中的,所以会影响性能。这时候我们就要做优化了,文档数很多的情况下尽量避免使用skip。通常可以给文档本身内置查询条件,来避免过大的 Skip,或者利用上次的结果来计算下一次查询。比如,我们可以根据创建时间排序之后取前10个作为第一页。要获取第二页的文档时,把第一页最后的创建时间作为查询条件,就可以获取第二页的文档了,以此类推,我们总可以找到一种方法实现不用skip的分页。
(3)避免使用$where
$where操作符功能强大且灵活,它可以将 JavaScript 表达式和 JavaScript 函数作为查询语句的一部分。在JavaScript表达式和函数中,可以使用 this 或obj来引用当前操作的文档,所以可以实现非常多的功能。
查询时,$where操作符不能使用索引,每个文档需要从 BSON 对象转换成 JavaSript 象后,才可以通过$where 表达式来运行。因此,它比常规查询要慢很多,一般情况下,要避免使用$where查询。
(4) Map Reduce 不能作实时查询
MapReduce有很好的聚合功能,用来进行统计,非常灵活且易于使用,它可以很好地与分片( sharding )结合使用,并允许大规模输出。但是 MapReduce 在执行过程中需要一定的交互,所以会比较慢。它适合处理大数据量的离线统计分析,不适合需要实时结果的场景。对于大数据的处理,MongoDB现在可以很好地跟 Hadoop 进行配合使用。
(5) 内嵌文档的查询
对于内嵌文档,mongoDB提供了@DBref数据结构来关联Primary文档和内嵌文档。
@DBRef的使用,主要是为了避免主文档直接引入从文档,因为直接内嵌的话,一旦从文档内容变了,那么主文档也需要跟着修改。所以,可以使用@DBRef,让主文档保留一下从文档的引用即可。
使用@DBRef以后,在查询主文档的时候,会自动关联从文档,把从文档的相关数据也取出来,一起返回。
但是,@DBRef有个缺点就是它比较占数据库空间,因为虽然它没有直接把从文档存下来,但它还是保留了一份从文档的引用,这份引用也需要分配文档空间,因此,如果主文档关联的从文档数量会不断增加,那么我们就不能使用@DBRef了,比如用户文档和用户的评价数据文档,如果把用户的评价数据使用@DBRef关联,那么占用的空间会越来越大,对数据库性能的影响也会越来越大。
对于这种情况,只能在主文档里存一个从文档的ID来做弱关联,查询的时候先查主文档,再通过从文档ID再查从文档,然后合一起返回。
(6) 模糊查询
MongoDB使用 $regex 操作符来设置匹配字符串的正则表达式。
使用$regex操作符:
db.collection.find({field:{$regex:"pattern",$options:"<options>"}})
db.collection.find({field:{$regex:/pattern/,$options:"<options>"}})
db.collection.find({field:{$regex:/pattern/<options>}})
以上查询也可以简写为:
db.collection.find({field:/pattern/<options>})
$regex操作符的使用场景:
在$in操作符中只能使用正则表达式对象,例如:{field:$in:[/^aaa/i,/^bbb/}}
在使用隐式的$and操作符中,只能使用$regex,例如:{field:{$regex:/^aaa/i, $nin:[‘bbb’]}}
当option选项中包含X或S选项时,只能使用$regex,例如:{field:{$regex:/aaa/,$options:”i”}}
options的使用:
$regex操作符中的option选项可以改变正则匹配的默认行为,它包括i, m, x以及S四个选项。i,m,x,s可以组合使用
options 注释:
i 忽略大小写,设置i选项后,模式中的字母会进行大小写不敏感匹配。
m 多行匹配模式,m选项会更改^和$元字符的默认行为,分别使用与行的开头和结尾匹配,而不是与输入字符串的开头和结尾匹配。
x 忽略非转义的空白字符,设置x选项后,正则表达式中的非转义的空白字符将被忽略,同时井号(#)被解释为注释的开头注,只能显式位于option选项中。
s 单行匹配模式,设置s选项后,会改变模式中的点号(.)元字符的默认行为,它会匹配所有字符,包括换行符(\n),只能显式位于option选项中。









网友评论