本章承诺过要通过JavaScript Shell来介绍MongoDB。你已经了解了数据操作和索引的基本知识,这里我将介绍一些技术,帮助你获得mongod进程的信息。举例来说,你可能想知道众多集合一共占用了多少空间,或者你在一个集合上定义了多少索引。此处详述的命令能帮助你诊断性能问题并监控数据。
我们还会了解MongoDB的命令界面。大多数能在MongoDB实例上执行的特殊非CRUD操作——从服务器状态检查到数据文件完整性校验——都是由数据库命令实现的。我将说明MongoDB上下文里的命令,并演示其易用性。最后,知道如何寻求帮助总是好的,所以我将指出在Shell里怎么获得帮助,以帮助你进一步了解MongoDB。
2.3.1 获取数据库信息
你经常想知道指定实例上到底有哪些集合与数据库,幸运的是MongoDB Shell提供了许多命令和语法糖,以此能获取系统相关的信息。
show dbs显示了系统上所有数据库的列表:
> show dbs
admin
local
test
tutorial
show collections显示了定义在当前数据库里的所有集合的列表。1如果目前还是选中了tutorial数据库,你会看到之前用过的集合:
1. 还可以键入范围更明确的show tables。
> show collections
numbers
system.indexes
users
你可能会对其中的system.indexes集合感到陌生。这是存在于每个数据库中的特殊集合,其中每一项都定义了数据库的一个索引。我们能直接查询该集合,但这样的输出不易阅读,还是像我们之前看到的那样,使用getIndexes方法更好一些。
为了获得数据库与集合更底层的信息,stats方法非常有用。在数据库对象上执行该方法时,会获得如下输出:
> db.stats
{
"collections" : 4,
"objects" : 200012,
"dataSize" : 7200832,
"storageSize" : 21258496,
"numExtents" : 11,
"indexes" : 3,
"indexSize" : 27992064,
"ok" : 1
}
我们还可以在单独的集合上执行stats命令:
> db.numbers.stats
{
"ns" : "tutorial.numbers",
"count" : 200000,
"size" : 7200000,
"storageSize" : 21250304,
"numExtents" : 8,
"nindexes" : 2,
"lastExtentSize" : 10066176,
"paddingFactor" : 1,
"flags" : 1,
"totalIndexSize" : 27983872,
"indexSizes" : {
"_id_" : 21307392,
"num_1" : 6676480
},
"ok" : 1
}
结果文档中的一些值仅在复杂的调试情况中才会有用。但最起码能知道指定集合和它的索引到底占用了多少空间。
2.3.2 命令工作原理
与截至目前本章所描述的插入、更新、删除和查询操作不同,某些MongoDB操作是数据库命令。数据库命令一般都是管理类命令,比如之前提到的stats方法,但它们也可能用于控制诸如MapReduce之类的核心MongoDB特性。
不管这些命令的功能是什么,它们的共同点是,在实现上它们都是对名为$cmd的特殊虚集合的查询。要明白这是什么意思,来看一个简单的例子。还记得我们是如何调用stats数据库命令的吗:
> db.stats
stats是一个辅助方法,它封装了Shell的命令调用方法。可以输入下列等效操作:
> db.runCommand( {dbstats: 1} )
该操作的输出和stats方法的输出是一样的。请注意,命令是由文档{dbstats: 1}来定义的。一般来说,我们可以向runCommand方法传递文档定义,借此运行各种命令。下面是运行集合统计命令的方法:
> db.runCommand( {collstats: 'numbers'} )
命令的输出你一定不会陌生。
要深入了解数据库命令,我们应该看看runCommand方法到底是怎么工作的。这并不难知道,因为MongoDB Shell会输出所有方法的实现,只要这些方法忽略括号就行了。我们可以改变下面的命令:
> db.runCommand
执行无括号的版本,一探究竟:
> db.runCommand
function (obj) {
if (typeof obj == "string") {
var n = {};
n[obj] = 1;
obj=n;
}
return this.getCollection("$cmd").findOne(obj);
}
函数中的最后一行无非就是查询$cmd集合。给它下个恰当的定义,数据库命令是对特殊集合$cmd的查询,查询选择器就是对命令本身的定义,仅此而已。你能想到如何手工运行集合统计命令吗?这很简单:
db.$cmd.findOne( {collstats: 'numbers'} );
使用runCommand辅助方法会更简单一点,但能了解内部细节总是好的。