db.a.find({},{"addrs":{"$slice":[5,10]}})上面的语句查询了从第6条数据开始,一共10条数据,如果从第六条数据开始,后面不足10条,那么返回后面的所有元素。
7、skip
使用Mongodb的时候【其他数据库也类似】,尽量少跳过过多的数据,这样会产生性能问题。8、有一个需求是从一个collection中随机选取出一个文档。
那么一般的做法是,先统计文档总数count,然后生成一个1到count的数字,去数据库中取出这个数字对应的文档。
这种方法是很低效的。要统计count,然后才能取出来数据。
高效的做法是:在存储数据的时候,同时存储一个random字段。这样如果最后result还是null,说明数据库中是没有记录了。随机取出一个文档的任务也完成了。
9、删除索引
db.a.dropIndex("indexname")
其中的indexname可以在system.index集合中查找。
10、查询内嵌文档
例如有如下文档:
{"content":"this is content","comments":[{"author":"naughty","score":3},{"author":"cc","score":4}]}
现在要查询author是naughty并且naughty的评论score大于3的记录,那么首先想到的查询是这样的:
db.a.find({'comments.author':'naughty'},{'comments.score':{$gt:3}})
但是记录多起来,查询的时候会发现,这样写是不对的。这样写,只要comments中有naughty并且有score是大于3,那么就会查询出来这条记录。查询结果不是我们想要的。
“要正确的指定一组条件,而不是单独的指定每个键。”书上如是说。
要这样写查询:
db.a.find({"comments":{"$elemMatch":{"author":"naughty","score":{"$gt":3}}}})这样就对了。
elemMatch将限定条件进行分组,仅当需要对一个内嵌文档的多个键进行查询的时候,才会用到。
11、group
假设有类似的一个需求:
有几条这样的文档
db.d.insert({"day":"2012-9-9","tags":['a','b','c','d']})
db.d.insert({"day":"2012-9-9","tags":['c','d']})
db.d.insert({"day":"2012-9-9","tags":['a','d']})
db.d.insert({"day":"2012-9-10","tags":['a','b']})
db.d.insert({"day":"2012-9-10","tags":['a','d']})
要查询每一天tags中出现次数最多的那个tag是什么。那么查询可以按照如下进行:
db.d.group({"key":{"day":true},"initial":{"tags":{}},"reduce":function(doc,res){
for(i in doc.tags){
if(doc.tags[i] in res.tags){
res.tags[doc.tags[i]]++;
}else{
res.tags[doc.tags[i]]=1;
}
}
},
"finalize":function(res){
var mp=0;
for(i in res.tags){
if(res.tags[i]>mp){
res.tag=i
mp=res.tags[i];
}
}
delete res.tags
}
})
其中finalize是在group动作结束之后,对聚合的每一个组调用一次。reduce函数是在聚合的时候进行调用,是用来生成分组的。reduce函数的两个参数分别是:当前文档和本组当前的聚合结果。
12、分片
分片【sharding】的目的是为了提高存储性能,那么什么时候进行分片呢?
第一、机器磁盘不够用了。
第二、机器已经不能满足写数据的性能需求。
第三、想把大数据都放在内存中以提高性能。
mongos就是mongodb的各个版本中都配备的路由器进程,它路由所有的请求,然后将结果聚合。它本身并不存储数据或者是配置信息(但是会缓存配置服务器的信息)。配置服务器存储了集群的配置信息:数据和片的对应关系。