MongoDB
中數據的基本單元,很是相似於關係型數據庫中的行,但更具備表現力;Collection
能夠看做是一個動態模式(Dynamic Schema
)的表;MongoDB
的一個實例能夠擁有多個相互獨立的數據庫 ( Database
),每個數據庫都擁有本身的集合;_id
,這個鍵在文檔所屬的集合中是惟一的;MongoDB
自帶了一個簡單但功能強大的 JavaScript Shell
,可用於管理 MongoDB
的實例或數據操做。文檔是 MongoDB
的核心概念,文檔就是鍵值對的有序集,下面的便是以 JavaScript
語言表現的一份文檔:javascript
{ "greeting" : "Hello, world!" }
在絕大多數狀況下,文檔的鍵是字符串(除了少數例外),鍵可使用任意的UTF-8 字符。java
\0
(空字符),這個字符用於表示鍵的結尾;.
和 $
具備特殊意義,只能在特定環境下使用,一般這兩個字符是被保留的,若是使用不當的話,驅動程序會有提示。MongoDB 不但區分類型,還區分大小寫,下面的兩個文檔是不一樣的:正則表達式
{ "foo" : "bar" }
與:mongodb
{ "Foo" : "bar" }
另外一個重要的事項是, MongoDB 的文檔不能有重複的鍵,例如:shell
{ "greeting" : "Hello, world!", "greeting" : "Hello, MongoDB!" }
文檔中的鍵/值對是有序的:數據庫
{ "x" : 1, "y" : 2 }
與:express
{ "y" : 2, "x" : 1 }
是不一樣的。json
集合就是一組文檔。若是將 MongoDB 中的一個文檔比喻爲關係型數據庫中的一行,那麼一個集合就至關於一張表。vim
集合是動態模式的,這意味着一個集合裏面的文檔但是各式各樣的,如何下面兩個文檔就能夠出現一個集合裏面:數組
{ "greeting" : "Hello, world!" }, { "foo" : 5 }
上面的兩個文檔,除了值不一樣外,鍵也不一樣,可是不建議像上面那樣作,一樣的文檔,咱們通常仍是放在一個特定的集合裏面更好,不論是速度、效率仍是結構上來說,都要更好。
集合使用名稱進行標識,集合名稱能夠是知足下列條件的任意 UTF-8 字符串:
""
);\0
字符(空字符),這個字符表示集合名的結束;system.
開頭,這是爲系統集合保留的前綴,例如: system.users
這個集合保存着數據庫的用戶信息,而 system.namespaces
集合保存着全部數據庫集合的信息;$
,由於某些系統生成的集合中飲食 $
。組織集合的一種慣例是使用 .
分隔不一樣命名空間的了集合,好比一個具備博客功能的應用可能包含兩個集合,分別是 blog.posts
和 blog.authors
。
在 MongoDB 中,多個文檔組成集合,而多個集合能夠組成數據庫,一個 MongoDB 能夠承載我個數據庫,每一個數據庫擁有 0 個或者多個集合,每一個數據庫都有獨立的權限,即使是在磁盤上,不一樣的數據庫也放置在不一樣的文件中。
數據庫經過名稱來標識,這點與集合相似,數據庫名能夠是知足如下條件的任意 UTF-8 字符串:
""
;/
、\
、.
、"
、*
、<
、>
、:
、|
、?
、$
(一個空格)、\0
(空字符);在這裏咱們須要記住一點,數據庫名最終會變成文件系統中的文件,而數據庫名就是相應的文件名,這是數據庫名有如此多限制的緣由。
另外,有一些數據庫名是保留的,能夠直接訪問這些有特殊語言的數據庫,以下:
admin:
從身份驗證的角度來說,這是 root
數據庫,若是有一個用戶添加到這個數據庫,則這個用戶將擁有全部數據庫的權限;
local
這個數據庫永遠都不能夠複製,且一臺服務器上全部的本地集合均可以存儲在這個數據訓中;
config
MongoDB 用戶分片設置時,分片信息會存儲在 config
數據庫中。
把數據庫名稱添加到集合名稱前,獲得集合的徹底限定名,即 命名空間 namespace
,命名空間的長度不得超過 121 字節,而實際應用中,應該小於100字節。
一般,MongoD 做爲網絡服務器來運行,客戶端可鏈接到該服務器並執行操做。要安裝 MongoDB ,能夠從官方網站下載相應的適合你係統的版本(http://www.mongodb.org/downloads)。下載完成以後,解壓,並把解壓以後獲得的文件夾複製或者移到至最終你想安裝的目錄便可。
我將其安裝在了 /Users/pantao/Workspace/MongoDB
這個目錄,同時,我將 MongoDB
的 bin
目錄加入了PATH
變量中:
vi ~/.bash_profile
加入以下一行:
export PATH="/Users/pantao/Workspace/MongoDB/bin:$PATH"
保存以後,運行:
source ~/.bash_profile
這個時候,我就能夠直接在任何地方啓動 MongoDB
或者進行相關的數據庫操做了,使用 mongod
命名啓動服務器:
pantaodeMacBook-Pro:MongoDB pantao$ mongod 2015-04-21T10:00:06.302+0800 I STORAGE [initandlisten] exception in initAndListen: 29 Data directory /data/db not found., terminating 2015-04-21T10:00:06.302+0800 I CONTROL [initandlisten] dbexit: rc: 100
出現上面這個錯誤是由於 /data/db
目錄不存在,若啓動時,不指定任何參數, MongoDB 會默認使用 /data/db
目錄存儲數據,咱們可使用 --dbpath
來指定其它的路徑,好比我使用的是下面這樣的命令啓動的:
mongod --dbpath /Users/pantao/Workspace/MongoDB/db
上面這個是個人工做目錄,直接將 MongoDB 的程序和數據庫放在一塊兒,我方便學習管理。
MongoDB 自帶有 JavaScript Shell ,能夠Shell 中使用命令行與 MongoDB 實例交互,Shell很是有用,經過它能夠執行管理操做,檢查運行實例,亦或是作其它嘗試。
使用 mongo
命令啓動 shell
:
pantaodeMacBook-Pro:MongoDB pantao$ mongo MongoDB shell version: 3.0.2 connecting to: test Welcome to the MongoDB shell. For interactive help, type "help". For more comprehensive documentation, see http://docs.mongodb.org/ Questions? Try the support group http://groups.google.com/group/mongodb-user Server has startup warnings: 2015-04-21T10:03:18.997+0800 I CONTROL [initandlisten] 2015-04-21T10:03:18.997+0800 I CONTROL [initandlisten] ** WARNING: soft rlimits too low. Number of files is 256, should be at least 1000 >
啓動時, shell
會打印出當前 shell
的版本號,鏈接到了哪一個庫以及一些幫助信息等,這是一個功能完備的 JavaScript
解釋器,能夠運行任意 JavaScript
程序,好比使用 JavaScript
標準庫或者定義以及調用 JavaScript 函數等。
shell
是一個獨立的 MongoDB客戶端,啓動時, shell
會連到 MongoDB 服務器的 test
數據庫,並將數據庫鏈接賦值給合局變量 db
,這個變量是經過 shell
訪問 MongoDB 的主要入口點,可使用 db
查看當前指向哪一個數據庫:
> db test
除了JavaScript語法外,MongoDB 還提供了一些語法糖,以幫助咱們更好的管理數據庫,好比:
> use foobar switched to db foobar
這個時候咱們能夠看到數據庫已經切換到 foobar
數據庫了:
> db foobar
在 shell
中查看查看或操做數據,會用到4個基本操做:建立、讀取、更新、刪除,即 CRUD
操做;
經過 db.createCollection()
函數能夠先建立一個集合:
> db.createCollection("blog") { "ok" : 1 }
insert
能夠將一個文檔添加到集合中:
> post = {"title": "這是一篇文章", "content": "這是文章的內容。","date" : new Date()} { "title" : "這是一篇文章", "content" : "這是文章的內容。", "date" : ISODate("2015-04-21T02:22:52.899Z") }
這是一個有效的 MongoDB 文檔,因此能夠用 insert
方法將其保存到集合中。
> db.blog.insert(post) WriteResult({ "nInserted" : 1 })
接着可使用 find
方法查找這篇文章:
> db.blog.find() { "_id" : ObjectId("5535b574b705494e688e218a"), "title" : "這是一篇文章", "content" : "這是文章的內容。", "date" : ISODate("2015-04-21T02:22:52.899Z") }
能夠看到咱們的數據都已經完整的保存下來了,同時,MongoDB 還爲咱們自動生成了一個 _id
參數。
find
與 findOne
方法能夠用於查詢集合裏的文檔:
> db.blog.findOne() { "_id" : ObjectId("5535b574b705494e688e218a"), "title" : "這是一篇文章", "content" : "這是文章的內容。", "date" : ISODate("2015-04-21T02:22:52.899Z") }
find
與 findOne
能夠接受一個查詢文檔做爲限定條件,使用 find
時,shell
會自動顯示最多 20 個匹配的文檔,也能夠獲取更多文檔。
使用 update
修改博客文章,它至少接受兩個參數,第一個是限定條件,第二個是新文檔,好比咱們如今要給 post
加上評論列表:
> post.comments = [] [ ]
而後,用新版本的 post
替換標題爲 《這是一篇文章》的文章:
> db.blog.update({"title":"這是一篇文章"},post) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.blog.findOne() { "_id" : ObjectId("5535b574b705494e688e218a"), "title" : "這是一篇文章", "content" : "這是文章的內容。", "date" : ISODate("2015-04-21T02:22:52.899Z"), "comments" : [ ] }
能夠看到,comments
已經更新到原來的那個 post
中去了。
使用 remove
能夠刪除集合中的文檔,若沒有任何限定參數,它將刪除集合中的全部數據,也能夠像下面這樣,刪除標題爲《這是一篇文章》的文章:
> db.blog.remove({"title":"這是一篇文章"}) WriteResult({ "nRemoved" : 1 }) > db.blog.find() >
MongoDB
的文檔與 JavaScript
中的對象相近,於是能夠認爲相似於 JavaScript
中的 JSON
,JSON 是一種簡單的數據表示方式,僅有 6種數據類型,分別爲 null
、bool
、number
、string
、array
和 object
。
MongoDB在保留 JSON 基本鍵/值對特性的基礎上,添加了其它的一些數據類型:
null
用於表示空值或者不存在的字段:
{ "x" : null }
bool
布爾型只有兩個值 true
與 false
:
{ "x" : true, "y" : false }
number
數值shell
默認使用 64位浮點型數值,對於整型值,可以使用 NumberInt
類或 NumberLong
類:
{ "pi" : 3.14, "x" : 3, "ni" : NumberInt("3"), "nl" : NumberLong("3") }
string
字符串UTF-8
類型的字符串均可以表示爲字符串類型的數據:
{ "x" : "this is a string.", "y" : "這是一個NB的字符串" }
date
日期日期被存儲 爲自新紀元以來通過的毫秒數,不存儲時區:
{ "x" : new Date() }
regular expression
正則表達式在進行查詢時,咱們能夠直接使用正則表達式做爲值,語法與 javascript
的相同:
{ "x" : /foobar/i }
array
數組數據列表或數據集能夠表達爲數組:
{ "a" : ["x", "y" , "z"] }
object id
對象ID對象ID是一個 12 字節的ID,它是文檔的惟一標識:
{ "x" : ObjectId() }
object id
以如下方式生成:
|0|1|2|3|4|5|6|7|8|9|10|11| | 時間戳 | 機器|PID| 計數器 |
hash
);_id
若插入文檔時,沒有提供 _id
鍵
object
內嵌文檔文檔能夠嵌套其它文檔,被嵌套的文檔做爲父文檔的值:
{ "o" : { "name" : "child object" } }
binary data
二進制數據任意字節的字符串,它不直直接在 shell
中使用,若是要將非 utf-8
字符保存到數據庫中,二進制數據是惟一的實現方式。
javascript
代碼查詢和文檔中能夠包括作生意 JavaScript 代碼:
{ "script" : function() { /* code goes here */ } }
timestamps
時間戳不一樣於 Date
類型的時間戳值,它是一個 64位長度的值,它是:
time_t
值,(Unix 時間戳)除了像前面那樣使用 shell
鏈接數據庫外,咱們還能夠在鏈接數據時指定服務器地址、端口號以及數據名等參數,好比:
mongo mongo-db.xingzhewujiang.com:30000/ahaInsight
啓動時,可讓 mongo shell
不鏈接任何的 mongod
,能夠經過 --nodb
參數:
mongo --nodb
啓動以後,咱們能夠在須要時執行 new Mongo(hostname)
命令就能夠鏈接到想要鏈接的 mongod
了:
> conn = new Mongo("host.name:30000") connection to host.name:30000 > db = conn.getDB("dbname") dbname
在使用 shell
的過程當中,還能夠隨時使用 help
命令查看幫助:
help db.help() help on db methods db.mycoll.help() help on collection methods sh.help() sharding helpers rs.help() replica set helpers help admin administrative help help connect connecting to a db help help keys key shortcuts help misc misc things to know help mr mapreduce show dbs show database names show collections show collections in current database show users show users in current database show profile show most recent system.profile entries with time >= 1ms show logs show the accessible logger names show log [name] prints out the last segment of log in memory, 'global' is default use <db_name> set current database db.foo.find() list objects in collection foo db.foo.find( { a : 1 } ) list objects in foo where a == 1 it result of the last line evaluated; use to further iterate DBQuery.shellBatchSize = x set default number of items to display on shell exit quit the mongo shell
除了交互式的使用 shell
外,咱們還能夠將命令保存在一個文件中,好比 script.js
,而後使用 mongo
命令直接執行它們,一次能夠傳入多個文件名,mongo shell
會依次執行傳入的腳本,而後退出:
mongo script.js script1.js
若是但願指定主機和端口來運行上面的腳本,還能夠這樣作:
mongo --quiet host.name:30000/dbname script.js script1.js
--quiet
可讓 mongo shell
不打印 MongoDB shell version...
這樣的提示信息。
在交互式的命令行中,還可使用 load()
函數加載並運行腳本:
> load("script.js") i am a string printed by script.js >
知道這個以後,咱們能夠把一些能用的函數保存到一個文件裏面,而後再將他們加載進 shell
交互界面裏面來:
建立一個名爲 connectTo.js
的文件,內容以下:
javascript/** * 連接到指定的數據庫,而後將 db 指向這個連接 */ var connectTo = function(port, dbname) { if (!port) { port = 27017; } if (!dbname) { dbname = "test" } db = connect("localhost:" + port + "/" + dbname) return db }
而後咱們進入 shell
:
bash> typeof connectTo undefined > load("connectTo.js") true > typeof connectTo function >
咱們可使用腳本讓能用的管理和任務自動化,好比,咱們想在每一次 shell
啓用時,都加載上面定義的那個函數,這個時候咱們能夠用到一個名爲 .mongorc.js
的文件。
在本身的家目錄中(不一樣的系統都不同),新建一個名爲 .mongorc.js
的文件,而後寫入下面這些內容:
print("你好,我來自 .mongorc.js 文件")
而後,從新進入 shell
:
mongo MongoDB shell version: 3.0.2 connecting to: test 你好,我來自 .mongorc.js 文件 >
該文件通常用得最多的就是用於刪除一些比較危險的 shell
輔助函數,好比刪除數據庫、索引等,好比下面這樣的:
javascriptvar no = function() { print("Not no my watch."); } // 禁止刪除數據庫 db.dropDatabase = DB.prototype.dropDatabase = no; // 禁止刪除集合 DBCollection.prototype.drop = no; // 禁止刪除索引 DBCollection.prototype.dropIndex = no;
shell
默認的提示是一個 >
符號,咱們能夠對該符號進行定製,好比最簡單的是,在每個提示符前面加上一個當前時間,這樣咱們就能夠很容易大概的知道,一些須要長時間執行的操做到底用了多久時間了:
javascriptprompt = function() { return (new Date()) + "> "; }
再一次進入 shell
:
bashmongo MongoDB shell version: 3.0.2 connecting to: test Tue Apr 21 2015 13:06:40 GMT+0800 (CST)> Tue Apr 21 2015 13:06:43 GMT+0800 (CST)>db test
另外一個方便的提示是顯示當前正在使用的數據庫:
javascriptprompt = function() { if (typeof db == 'undefined') { return '(nodb)>'; } // 檢查最後使用的數據庫操做 try { db.runCommand({getLastError:1}); } catch (e) { print(e); } return db + "> "; }
再一次進入 shell
:
bashmongo MongoDB shell version: 3.0.2 connecting to: test test>
shell
對多行編輯頗有限,若編輯了多行,忽然發現前面有一行有錯誤,這是不能修改的,可是它提供了一種方法,讓你能夠在 shell
中很訪問的使用外部的第三方編輯器,保存並退出編輯器以後,會對你修改的值進行從新解析,並從新加載回 shell
中,一樣使用 .mongorc.js
,在其中加入下面這一行:
EDITOR = "/usr/bin/vim"
而後進入 shell
:編輯一個複雜一點兒的變量:
bashmongo MongoDB shell version: 3.0.2 connecting to: test > var post = { ... title: "這是一篇文章的內容", ... content: "這是一篇文章的標題", ... author: "潘韜" ... } > post { "title" : "這是一篇文章的內容", "content" : "這是一篇文章的標題", "author" : "潘韜" } > edit post > post { "title" : "這是一篇文章的標題", "content" : "這是一篇文章的內容", "author" : "潘韜" } >
絕大多數時候,咱們可使用 db.collectionName
這種方式訪問一個數據庫中的集合,可是也有例外,好比 db.version
就不能訪問到名稱爲 version
的集合,由於 version
是 db
的一個方法名,能夠用來顯示當前的數據庫版本信息。那麼咱們就得使用其它的方法了,好比:
> db.getCollection("version"); test.version
有些時候,咱們的集合裏面還可能使用了不少變態的奇怪的名稱,好比 &$*%#
,使用 db.&$*%#
是非法的,可是咱們卻可使用 db.getCollection("&$*%#")
來獲取該集合,一樣的,咱們還有一種更加直接的方法,就是相似於JavaScript的數組訪問語法,像下面這樣:
db["&$*%#"].find()