本章承诺过要通过JavaScript Shell来介绍MongoDB。你已经了解了数据操作和索引的基本知识,这里我将介绍一些技术,帮助你获得mongod
进程的信息。举例来说,你可能想知道众多集合一共占用了多少空间,或者你在一个集合上定义了多少索引。此处详述的命令能帮助你诊断性能问题并监控数据。
我们还会了解MongoDB的命令界面。大多数能在MongoDB实例上执行的特殊非CRUD操作——从服务器状态检查到数据文件完整性校验——都是由数据库命令实现的。我将说明MongoDB上下文里的命令,并演示其易用性。最后,知道如何寻求帮助总是好的,所以我将指出在Shell里怎么获得帮助,以帮助你进一步了解MongoDB。
2.3.1 获取数据库信息
你经常想知道指定实例上到底有哪些集合与数据库,幸运的是MongoDB Shell提供了许多命令和语法糖,以此能获取系统相关的信息。
show dbs
显示了系统上所有数据库的列表:
> show dbsadminlocaltesttutorial
show collections
显示了定义在当前数据库里的所有集合的列表。1如果目前还是选中了tutorial
数据库,你会看到之前用过的集合:
1. 还可以键入范围更明确的show tables
。
> show collectionsnumberssystem.indexesusers
你可能会对其中的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
辅助方法会更简单一点,但能了解内部细节总是好的。