上一篇文章: MongoDB指南---三、MongoDB基础知识-数据类型
下一篇文章: MongoDB指南---五、建立、删除文档
本节将介绍如何将shell做为命令行工具的一部分来使用,如何对shell进行定制,以及shell的一些高级功能。
在上面的例子中,咱们只是链接到了一个本地的mongod实例。事实上,能够将shell链接到任何MongoDB实例(只要你的计算机与MongoDB实例所在的计算机可以连通)。在启动shell时指定机器名和端口,就能够链接到一台不一样的机器(或者端口):shell
$ mongo some-host:30000/myDB MongoDB shell version: 2.4.0 connecting to: some-host:30000/myDB
db如今就指向了some-host:30000上的myDB数据库。
启动mongo shell时不链接到任何mongod有时很方便。经过--nodb参数启动shell,启动时就不会链接任何数据库:数据库
$ mongo --nodb MongoDB shell version: 2.4.0 >
启动以后,在须要时运行new Mongo(hostname)命令就能够链接到想要的mongod了:segmentfault
> conn = new Mongo("some-host:30000") connection to some-host:30000 > db = conn.getDB("myDB") myDB
执行完这些命令以后,就能够像日常同样使用db了。任什么时候候均可以使用这些命令来链接到不一样的数据库或者服务器。数组
因为mongo是一个简化的JavaScript shell,能够经过查看JavaScript的在线文档获得大量帮助。对于MongoDB特有的功能,shell内置了帮助文档,可使用help命令查看:服务器
> help db.help() help on db methods db.mycoll.help() help on collection methods sh.help() sharding helpers ... show dbs show database names show collections show collections in current database show users show users in current database ...
能够经过db.help()查看数据库级别的帮助,使用db.foo.help()查看集合级别的帮助。
若是想知道一个函数是作什么用的,能够直接在shell输入函数名(函数名后不要输入小括号),这样就能够看到相应函数的JavaScript实现代码。例如,若是想知道update函数的工做机制,或者是记不清参数的顺序,就能够像下面这样作:dom
> db.foo.update function (query, obj, upsert, multi) { assert(query, "need a query"); assert(obj, "need an object"); this._validateObject(obj); this._mongo.update(this._fullName, query, obj, upsert ? true : false, multi ? true : false); }
本书其余章都是以交互方式使用shell,可是也能够将但愿执行的JavaScript文件传给shell。直接在命令行中传递脚本就能够了:编辑器
$ mongo script1.js script2.js script3.js MongoDB shell version: 2.4.0 connecting to: test I am script1.js I am script2.js I am script3.js $
mongo shell会依次执行传入的脚本,而后退出。
若是但愿使用指定的主机/端口上的mongod运行脚本,须要先指定地址,而后再跟上脚本文件的名称:函数
$ mongo --quiet server-1:30000/foo script1.js script2.js script3.js
这样能够将db指向server-1:30000上的foo数据库,而后执行这三个脚本。如上所示,运行shell时指定的命令行选项要出如今地址以前。
能够在脚本中使用print()函数将内容输出到标准输出(stdout),如上面的脚本所示。这样就能够在shell中使用管道命令。若是将shell脚本的输出管道给另外一个使用--quiet选项的命令,就可让shell不打印“MongoDB shell version…”提示。
也可使用load()函数,从交互式shell中运行脚本:工具
> load("script1.js") I am script1.js >
在脚本中能够访问db变量,以及其余全局变量。然而,shell辅助函数(好比"use db"和"show collections")不能够在文件中使用。这些辅助函数都有对应的JavaScript函数,如表2-1所示。
表2-1 shell辅助函数对应的JavaScript函数post
辅助函数 | 等价函数 |
---|---|
use foo | db.getSisterDB("foo") |
show dbs | db.getMongo().getDBs() |
show collections | db.getCollectionNames() |
可使用脚本将变量注入到shell。例如,能够在脚本中简单地初始化一些经常使用的辅助函数。例如,下面的脚本对于本书的复制和分片部份内容很是有用。这个脚本定义了一个connectTo()函数,它链接到指定端口处的一个本地数据库,而且将db指向这个链接。
// defineConnectTo.js /** * 链接到指定的数据库,而且将db指向这个链接 */ var connectTo = function(port, dbname) { if (!port) { port = 27017; } if (!dbname) { dbname = "test"; } db = connect("localhost:"+port+"/"+dbname); return db; };
若是在shell中加载这个脚本,connectTo函数就可使用了。
> typeof connectTo undefined > load('defineConnectTo.js') > typeof connectTo function
除了添加辅助函数,还可使用脚本将通用的任务和管理活动自动化。
默认状况下,shell会在运行shell时所处的目录中查找脚本(可使用run("pwd")命令查看)。若是脚本不在当前目录中,能够为shell指定一个相对路径或者绝对路径。例如,若是脚本放置在~/my-scripts目录中,可使用load("/home/myUser/my-scripts/defineConnectTo.js")命令来加载defineConnectTo.js。注意,load函数没法解析~符号。
也能够在shell中使用run()函数来执行命令行程序。能够在函数参数列表中指定程序所需的参数:
> run("ls", "-l", "/home/myUser/my-scripts/") sh70352| -rw-r--r-- 1 myUser myUser 2012-12-13 13:15 defineConnectTo.js sh70532| -rw-r--r-- 1 myUser myUser 2013-02-22 15:10 script1.js sh70532| -rw-r--r-- 1 myUser myUser 2013-02-22 15:12 script2.js sh70532| -rw-r--r-- 1 myUser myUser 2013-02-22 15:13 script3.js
一般来讲,这种使用方式的局限性很是大,由于输出格式很奇怪,并且不支持管道。
若是某些脚本会被频繁加载,能够将它们添加到mongorc.js文件中。这个文件会在启动shell时自动运行。
例如,咱们但愿启动成功时让shell显示一句欢迎语。为此,咱们在用户主目录下建立一个名为.mongorc.js的文件,向其中添加以下内容:
// mongorc.js var compliment = ["attractive", "intelligent", "like Batman"]; var index = Math.floor(Math.random()*3); print("Hello, you're looking particularly "+compliment[index]+" today!");
而后,当启动shell时,就会看到这样一些内容:
$ mongo MongoDB shell version: 2.4.0- preconnecting to: test Hello, you're looking particularly like Batman today! >
为了实用,可使用这个脚本建立一些本身须要的全局变量,或者是为太长的名字建立一个简短的别名,也能够重写内置的函数。.mongorc.js最见的用途之一是移除那些比较“危险”的shell辅助函数。能够在这里集中重写这些方法,好比为dropDatabase或者deleteIndexes等辅助函数添加no选项,或者取消它们的定义。
var no = function() { print("Not on my watch."); }; // 禁止删除数据库 db.dropDatabase = DB.prototype.dropDatabase = no; // 禁止删除集合 DBCollection.prototype.drop = no; // 禁止删除索引 DBCollection.prototype.dropIndex = no;
改变数据库函数时,要确保同时对db变量和DB原型进行改变(如上例所示)。若是只改变了其中一个,那么db变量可能没有改变,或者这些改变在新使用的全部数据库(运行use anotherDB命令)中都不会生效。
如今,若是试图调用这些函数,就会获得一条错误提示。注意,这种方式并不能保护数据库免受恶意用户的攻击,只能预防本身的手误。
若是在启动shell时指定--norc参数,就能够禁止加载.mongorc.js。
将prompt变量设为一个字符串或者函数,就能够重写默认的shell提示。例如,若是正在运行一个须要耗时几分钟的查询,你可能但愿完成时在shell提示中输出当前时间,这样就能够知道最后一个操做的完成时间了。
prompt = function() { return (new Date())+"> "; };
另外一个方便的提示是显示当前使用的数据库:
prompt = function() { if (typeof db == 'undefined') { return '(nodb)> '; } // 检查最后的数据库操做 try { db.runCommand({getLastError:1}); } catch (e) { print(e); } return db+"> "; };
注意,提示函数应该返回字符串,并且应该当心谨慎地处理异常:若是提示中出现了异常会对用户形成困惑!
一般来讲,提示函数中应该包含对getLastError的调用。这样能够捕获数据库错误,并且能够在shell断开时自动从新链接(好比重启了mongod)。
能够在.mongorc.js中定制本身想要的提示。也能够定制多个提示,在shell中能够自由切换。
shell的多行支持是很是有限的:不能够编辑以前的行。若是编辑到第15行时发现第1行有个错误,那会让人很是懊恼。所以,对于大块的代码或者是对象,你可能更愿意在编辑器中编辑。为了方便地调用编辑器,能够在shell中设置EDITOR变量(也能够在环境变量中设置):
> EDITOR="/usr/bin/emacs"
如今,若是想要编辑一个变量,可使用"edit 变量名"这个命令,好比:
> var wap = db.books.findOne({title: "War and Peace"}) > edit wap
修改完成以后,保存并退出编辑器。变量就会被从新解析而后加载回shell。
在.mongorc.js文件中添加一行内容,EDITOR="编辑器路径";,之后就没必要单独设置EDITOR变量了。
可使用db.collectionName获取一个集合的内容,可是,若是集合名称中包含保留字或者无效的JavaScript属性名称,db.collectionName就不能正常工做了。
假设要访问version集合,不能直接使用db.version,由于db.version是db的一个方法(会返回当前MongoDB服务器的版本):
> db.version function () { return this.serverBuildInfo().version; }
为了访问version集合,必须使用getCollection函数:
> db.getCollection("version"); test.version
若是集合名称中包含无效的JavaScript属性名称(好比foo-bar-baz和123abc),也可使用这个函数来访问相应的集合。(注意,JavaScript属性名称只能包含字母、数字,以及"$"和"_"字符,并且不能以数字开头。)
还有一种方法能够访问以无效属性名称命名的集合,那就是使用数组访问语法:在JavaScript中,x.y等同于x['y']。也就是说,除了名称的字面量以外,还可使用变量访问子集合。所以,若是须要对blog的每个子集合进行操做,可使用以下方式进行迭代:
var collections = ["posts", "comments", "authors"]; for (var i in collections) { print(db.blog[collections[i]]); }
而没必要这样:
print(db.blog.posts); print(db.blog.comments); print(db.blog.authors);
注意,不能使用db.blog.i,这样会被解释为test.blog.i,而不是test.blog.posts。必须使用db.blog[i]语法才能将i解释为相应的变量。
可使用这种方式来访问那些名字怪异的集合:
> var name = "@#&!" > db[name].find()
直接使用db.@#&!进行查询是非法的,可是可使用db[name]。
上一篇文章: MongoDB指南---三、MongoDB基础知识-数据类型
下一篇文章: MongoDB指南---五、建立、删除文档