近年來由於社群網站和雲端技術的興起,讓大量原本屬於資訊接收的使用者,變成資訊的產生和提供者,也因此促成了巨量資料存取以及資料庫動態擴展的強烈需求;部份為了資料量龐大、無法及時擴充資料庫而若惱的業者,紛紛捨棄了傳統的關聯式資料庫而改採分散式非關聯式資料庫來解決這些巨量資料的問題,此類型的資料庫,即目前相當流行的NoSQL資料庫;在此需求所帶動的潮流下,各種不同形態的NoSQL資料庫如雨後春筍般竄起,http://nosql-database.org/的表格中,就洋洋灑灑的列出了目前已知的NoSQL種類(已經達到150種),其中,MongoDB是眾多noSQL資料庫軟體中較為人熟知的一種,在四大類型(註)noSQL資料庫中,它是屬於最容易使用與上手的文檔類型資料庫。
NoSQL種類
最早NoSQL的確是指No SQL這個意思,可回溯至90年代某個開放原始碼的關聯式資料庫 [Strozzi NoSQL],這個資料庫系統號稱不使用SQL作為查詢語言,而是使用Shell script來維護資料庫,因此一般人認為NoSQL應該是指No SQL,以代表它們不支援SQL這種結構性查詢語法,但近來則普遍將NoSQL視為「Not Only SQL」,即不只是SQL的意思,希望揉合SQL優點並混用關聯式資料庫和NoSQL資料庫來達成最佳的儲存效果。
一般我們將NoSQL依其資料模型分類為「Key-value Stores」、「Document Databases」、「Graph Databases」三種,也有第人提出第四種形態「Column Family Store」,或翻譯為「列族」或「欄位群」(個人認為這個比較貼切),它屬於一種「Key-value類型」的變形,適合用於大量的數據資料分佈在相當多台機器的情況。
但這種分類方式雖然有用但較粗糙,像「Key-value Stores」與「Document Databases」之間的界線是相當模糊的,因為在每個Key對應的Value值也可以塞入Document型態的內容,因此許多資料庫並不單純僅僅屬於某種型態種類,例如以OrientDB來說,它自稱是文件資料庫也是圖形資料庫;但基本上「Key-value Stores」、「Document Databases」、「Column Family Store」這三種有著同通的特性,我們都稱它們是屬於聚集導向,亦即,每個聚集都擁有一個鍵(key)來取得資料。
1. Key-values Stores 鍵值資料庫
它是利用一種雜湊表(hash table)的概念,使用一個唯一的鍵值(Key value)指向一個特定的值或資料,格式如同「Key:Value」;這種形態的資料庫相當簡單且容易導入使用,但若僅僅用於單純查詢或更新某個值的話,其效率比不上傳統的關連式資料庫。
Key-values Stores範例:
BerkeleyDB、LevelDB、Memcached、Project Voldemort、Redis、Riak
2. Column Family Stores 欄位群
這種形態的資料庫適用於大量資料分佈於很多台主機的情況,也是採用Key-values 的雜湊方式,但每個Key值會對映到不同的columns,而非單一的value。
Column Family Stores範例:
Amazon SimpleDB、Cassandra、HBase、Hypertable
3. Document Databases 文件資料庫
文件儲存概念最早為Lotus Notes所採用,NoSQL也導入了此種方式,但實際上,NoSQL中所謂的Document Databases並非我們認知的實體文字檔案,而是一種資料表示方式(如json);如同Key-Value Stores般,Document Databases的每組Key所對應的value內容就是json資料表示方式的內容,而非一般人以為的實體文檔。
所以Document Databases可以作到巢狀的方式,在每個Value中又可定義為另一組Key:Value (如 {Key: {Key:Value, Key:Value} } ),使得Document Databases進行查詢時比起單純的Key-Value Stores更具效率。
Column Family Stores範例:
CouchDB、MongoDB、OrientDB、RavenDB、Terrastore
4. Graph Databases 圖學資料庫
依字面意義,我們會很容易誤解Graph Databases是針對圖片的資料庫檢索,但實際不然,Graph指的是每個資料節點之間的架構及關係;一般而言Graph Databases並沒有標準的作法,最基本包括了節點(Node)、關係(Relation)和屬性(Property)三種結構;若繪製出來可能會如同樹狀或網狀般不同的格式,因此Graph Databases相當適用用於地理圖資或者朋友、親屬、社交等系統,此類資料庫最大的特性是對複雜性的擴充力,關係越複雜的資料越適合使用圖學資料庫。
Graph Databases範例:
FlockDB、HyperGraphDB、Infinite Graph、Neo4J、OrinetDB
安裝MongoDB
MongoDB屬於Document Databases的NoSQL開源軟體,它支援三種的平台:Windws、Linux與Mac OS,本文以Windows 7平台作為操作及示範,另需注意的是,自2.2版的MongoDB開始,已不再支援XP系統,此外,如果是Server 2008 R2或者是Windows 7的系統,需要額外先安裝一個微軟的hotfix KB2731284。(http://support.microsoft.com/kb/2731284)
- 安裝:解壓縮下載後的檔案,移至適當地方並重新命名。(MongoDB是一支標準的綠色程式,不需安裝即可在任何路徑下直接執行)
cd \
move C:\mongodb-win32-* C:\mongodb
- 路徑:MongoDB需要一個資料夾來存放檔案,預設是C:\data\db,您也可以自行建立其它的目錄,並在啟動MongoDB時用—dbpath參數來指定。
- 啟動:要啟動MongoDB很簡單,只要執行mongod.exe就行了。
C:\mongodb\bin\mongod.exe
我們會看到waiting for connections的訊息出現在視窗中,這表示MongoDB已經成功的在運作了。
如果DB資料夾需另外指定:
C:\mongodb\bin\mongod.exe --dbpath d:\test\mongodb\data
如果DB資料夾路徑中有空白字元:
C:\mongodb\bin\mongod.exe --dbpath "d:\test\mongo db data"
- 測試:開啟另一個DOS視窗,執行 C:\mongodb\bin\mongo.exe
Mongo.exe預設會連到本機的27017 port(mongod listen的port),此時,你可以觀察到mongod回應的connection accepted訊息。
MongoDB資料庫架構
Document:
MongoDB中的Document,是由一串key:value形態組合而成的Json格式字串,它類似於關連式資料庫的Record;其中的key,等同於關連式資料庫Record中的欄位,而value,則類似關連式資料庫欄位的值;但MongoDB Document的key:value是動態性,可以隨意增減的,而傳統關連式資料庫的欄位則無法隨意更改,一更改便會影響到該table全部的records。
例如,下方的json字串可視為一個document
{
user:'user2',
message: 'My second comments',
dateCreated: new Date(2011,1,25,7,45),
like: 5
}
Collection:
Collection是一群Documents的集合,它相當類似於關連式資料庫中所謂的table;每個Collection只會屬於一個資料庫,需注意的是,MongoDB的Collection結構是動態的,意謂著相同Collection下的每個Document可以擁有不同的key值定義,這點與關連式資料庫不同,關連式資料庫中table的每筆Record皆擁有相同的欄位定義,不會有欄位相異的情況。
Database:
與關連式資料中,每個Database會有好幾個tables一樣,Collections會屬於某一個Database,從檔案系統的角度來看,每個Database會有數個檔案(視其擁有幾個Collections而定)。
瞭解JSON格式:
JSON為JavaScript Object Notation的縮寫,與XML一樣,屬於資料交換用途的一種檔案格式,但它比起XML,具有更易於閱讀、更精簡、檔案更小、更方便機器解析和生成等特性,因此,近年來在一些需要快速傳輸的WEB領域,已逐漸取代XML成為資料交換的標準;此外,一些NoSQL資料庫也應用JSON成為其儲存格式的標準(如MongoDB、RavenDB以及CouchDB等)。
JSON的檔案格式:
- 以"{"開始,以"}"結尾
- 每個KEY與Value中間用":"分隔
- 若該KEY的Value不止一個,則用”,”分隔每個Value,最後用"[" 與 "]"包圍。
- 不同的"KEY:Value"之間用","分隔
{ ←以"{"開始,以"}"結尾
'familys' = [ ← familys collection有二筆documents,各分別有二組Key:Value,
{'name' : 'Bruce', 用”,”分隔每個Value,最後用"[" 與 "]"包圍(表示為陣列)。
'age' : 18,
'sex' : 'male'}, ←每筆document資料之間用","分隔
{'name' : 'Sherry',
'age' : 16,
'sex' : 'famale'}
]
}
上面的json內容,表示在familys這個collection下,有兩筆資料如下:
names
|
age
|
sex
|
Bruce
|
18
|
male
|
Sherry
|
16
|
female
|
基本操作
A) 顯示目前使用的DB:啟動MongoDB時,預設開啟的資料庫是Test,輸入db指令,可以顯示目前使用中的資料庫。
> db
Test
B) 顯示目前所有的資料庫以及使用的大小:
> show dbs
local 0.078125GB
test 0.203125GB
C) 切換到另一個資料庫local
> use local
switched to db local
> db
local
D) 輸入help可顯示所有的指令及說明
> help
E) 建立新資料庫
直接使用use {DBNAME},若沒有該資料庫,則會自動新增。
> use mydb
switched to db mydb
F) 新增資料到資料庫
我們先定義j與k的內容,再利用db.testData.insert新增到資料庫中;請注意,db.testData.insert( j )中的testData,代表collection的名稱。
> j = { name : "mongo" }
{ "name" : "mongo" }
> k = { x : 3 }
{ "x" : 3 }
> db.testData.insert( j )
> db.testData.insert( k )
您會發現,在mongoDB的模式下也可以執行javascript的命令,這對於我們在處理相關資料庫操作上,是相當方便的。
G) 顯示資料庫中的collections列表(system.indexes預設每個DB都會有)
> show collections
system.indexes
testData
H) 使用find()可列出該collection的所有文件
> db.testData.find()
{ "_id" : ObjectId("53392bd6b19ffea4731632cd"), "name" : "mongo" }
{ "_id" : ObjectId("53392bddb19ffea4731632ce"), "x" : 3 }
MongoDB會自動為每筆文件附加上唯一的欄位_id。
I) 以陣列方式來使用:hasNext()與next()
hasNext()傳回true如果下一個指標有document,next()會傳回下一個document。
> var c = db.testData.find()
> while ( c.hasNext() ) printjson( c.next() )
{ "_id" : ObjectId("53392bd6b19ffea4731632cd"), "name" : "mongo" }
{ "_id" : ObjectId("53392bddb19ffea4731632ce"), "x" : 3 }
在上例中,db.testData.find()所回傳的列表會放在c變數中,我們再利用hasNext()與next()來操控c變數中的資料,其中,printjson()此函數是將json格式的資料顯示出來,此外, 也可以使用printjson(c[1]) 的方式直接指定第幾筆資料。
J) 搜尋特定文件:find()與findOne()
我們要搜尋文件中X值為3的資料,可以用 { x:3 }
> db.testData.find( {x:3} )
{ "_id" : ObjectId("53392bddb19ffea4731632ce"), "x" : 3 }
如果我們只需要傳回一筆文件,可以用findOne()取代find()
> db.testData.findOne( {x:3} )
{ "_id" : ObjectId("53392bddb19ffea4731632ce"), "x" : 3 }
如果在find後方接limit(),則可以限制回傳的筆數
> db.testData.find().limit(2)
{ "_id" : ObjectId("53392bd6b19ffea4731632cd"), "name" : "mongo" }
{ "_id" : ObjectId("53392bddb19ffea4731632ce"), "x" : 3 }
> db.testData.find().limit(1)
{ "_id" : ObjectId("53392bd6b19ffea4731632cd"), "name" : "mongo" }
結語
以上簡要介紹了NoSQL以及MongoDB的安裝和基本操作,會發現MongoDB相當容易安裝且它的查詢語言並不複雜;一般初接觸NoSQL,可以會誤以為可以用NoSQL來取代傳統的資料庫如MSSQL、Oracle或mySQL等,但其實兩者各有其應用範圍,如果系統對於資料即時且正確的要求性相當高,例如訂單、付款、會員資料等交易性資料,那麼必須優先考慮傳統關聯性資料庫不可,但關聯性資料庫的最大缺陷在於擴展性不夠,雖然各個資料庫廠家都有cluster的解決方案,但擴展性都十分有限,因此,如果您的資料量龐大隨時都可能需要增加資料庫的空間,且對資料的正確與即時性能接受短時間不正確並最終會正確(例如Facebook按讚的數量統計),那麼NoSQL會是適合的選擇。
沒有留言:
張貼留言