第三章 - 掌握查找
第一章对find
命令作了一些简单的介绍,除了选择器以外,find
还有很多其他的特性。之前有提到过find
返回的结果是一个游标。现在就将对这点做深入的讨论。
域的选择
在开始游标的话题之前,您需要知道find
还有第二个可选参数。该参数是一个列表,用户在这个表中指明要求find
读取的域。例如,可以用下面的命令获取所有独角兽的名字:
db.unicorns.find(null, {name: 1});
_id
域在默认情况下总是会被find
返回的。{name:1, _id: 0}
可以显式地从返回结果中排除它。
除了上面排除_id
域的情况外,不可以将选择与排除的表达式混在一起使用(译者:比如说{_id:1, name:0}
或者{name:1, gender:0}
都是不合法的)。想一想其实也合乎逻辑:不是显式地选择,就是说明哪些域需要排除。
排序
我已经好几次提到,find
返回的是一个游标,对游标的操作直到必要的时候才会执行。然而在shell中的感觉却是find
马上就执行了。这仅仅是find
在shell中的行为。我们可以通过把find
和一个命令连接起来的方法观察find
真正的行为。我们先用sort
来做这个实验。sort
的运作方式有点像上一节提到的域的选择:标明哪些域需要排序,用1表示升序,用-1表示降序。例如:
//最重的独角兽排在第一
db.unicorns.find().sort({weight: -1})
//优先按名字排序再按吸血技能排序
db.unicorns.find().sort({name: 1, vampires: -1})
如同关系数据库,MongoDB也可以利用索引进行排序。我们会在后面再详细讨论索引。只是您要知道,当没有建立索引时,MongoDB是限制排序对象大小的(译者:目前是16MB)。也就是说,如果您尝试对一个大规模的结果的集进行排序,而又没有为这个结果建立索引,那么就会看到错误的提示。对一些人来说,这是MongoDB的局限性。但是说实话,我真希望更多的数据库能够像MongoDB那样拒绝执行那些未经优化的查询。(我倒不是要把每个MongoDB的缺点都硬掰成优点,只是我见过太多缺乏优化的数据库了,所以我真的很希望它们能有一个严格模式
以限制未经优化的查询。)
分页(paging)
对结果的分页可以通过limit
以及skip
这两个游标操作来实现。比如可以用以下的命令来得到第二,第三重的独角兽:
db.unicorns.find().sort({weight: -1}).limit(2).skip(1)
对非索引域进行排序是很麻烦的,联合limit
一起使用sort
是避免此类麻烦的好方法。
计数
在shell中我们可以对一个集合直接地执行count
命令,例如:
db.unicorns.count({vampires: {$gt: 50}})
而现实中count
却是一个游标的操作,shell只是提供了一条捷径而已。在使用没有提供这些捷径的驱动时,就要用到下面的命令(在shell中也有用):
db.unicorns.find({vampires: {$gt: 50}}).count()
本章小结
find
和cursors
的使用是比较直接明了的。还有一些额外的命令,有一些会在后面的章节继续介绍,其他的几乎都只是用在很少见的情况了。到现在为止您应该可以比较自如的在mongo的shell工作,也了解了MongoDB的基础知识了。