上一篇文章: 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指南---五、建立、刪除文檔