Mongo DB
X
JavaScript
TonyQ
JavaScript.tw
小分享、聊天、寫 Code
得先交待一下為什麼很久沒出現......
可以再度辦聚會真是一種小確幸~~(欸)
Mongo DB
這是什麼?
DB = Database ?
MySQL ? MS SQL?
為什麼 JavaScript 開發者跟資料庫有關係?
如果你以前有學過 SQL
先忘了他
因為這是
NO-SQL
Database
比起傳統 RDBMS 資料庫管理者
JavaScript 開發者離 MongoDB 更近。
why?
Document-oriented database
他儲存的最小單位是 "document",
採用的是 BSON 格式。
BSON : Binary JSON
So what ?
他的內建查詢介面、內建預存函式的寫法
100% JavaScript
資料庫還有分寫法?
不是開 table 寫 schema,作 table join ,
用資料表達式把資料撈出來?
Mongo DB
很不一樣
不要求一定要固定的 Schama
不鼓勵 Table Join
沒有內建的交易機制(transation)
以上就如同大多數 NoSQL 資料庫一樣
另外他還是以 Document 為單位 (document-oriented)
但
你肯定還是不知道這關我們什麼屁事,
所以,不廢話進實作。
先看 Demo
( 直接看投影片的請參考這個專案
https://github.com/tony1223/mongodb-php-messageboard-sample/tree/only-message )
這裡開始得安裝 Mongo DB
是獨立服務、會佔用一個 Port
要認真用的一定要用 64 bit OS裝 64 bit 版,不然你一定會後悔。
另外注意:Data Folder
安裝 mongodb
下載後會分成 mongo (client),mongod (server),
上一頁中的文件教學有寫怎麼啟動 server。
預設 server port 是 27017 。
試著玩玩看
mongo
show database;
use message;
show collections;
什麼是 collection?
Collection ,集合。
基本上就是一個 Array,一群資料的集合中心,
平常系統通常會把資料加到 collection 與編輯資料。
試著玩玩看2
//查查看有幾筆資料
db.messages.count()
//顯示全部
db.messages.find()
試著修改 database ?
直接拿出 JS 物件出來修改的方法 (有趣但有風險)
var message = db.messages.find().next();
message.content = "modifed";
db.messages.save(message);
----------------------------------------------
用 mongo collection 內建的函式的作法
db.messages.update({_id:ObjectID("xxxxxxxxxxx")},
{$set:{content:"modified"}})
_id 是 ?
系統內建幫你產生的 uuid ,
用來作為 mongodb 核心識別用。
不能重複。
到這裡,你應該會覺得自己在寫 JS 多於在操作資料庫。XD
但,這跟我們平常的資料庫,有什麼不一樣?
我們來把 collection 砍掉重練
重建資料庫...? 咦
(其實不用建,因為本來就可以新增彈性欄位的 document )
進階版的 Demo Site
(可以多一層回應)
只看投影片的,可以參考 Repo
回應怎麼存?
{ "_id": "532362819d8d3fc02800002b", "content": "Test", "createDate": 1394827905000, "name": "TonyQ", "replied": [ { "name": "Guest1", "content": "message1", "createDate": 1394828761000 }, { "name": "Guest2", "content": "message2", "createDate": 1394828770000 } ]
}
一樣試著用 mongo shell 操作
var message = db.messages.find({id:ObjectID("xxxxxxx")}).next();
message.replied = message.replied || [];
message.replied.push({
"replied": {
"name": "Guest1",
"content": "message1",
"createDate": 1394828761000
}
});
db.messages.save(message);
db.message.update({id:ObjectID("xxxxxxx")},{
"$push": { "replied": { "name": "Guest1", "content": "message1", "createDate": 1394828761000 } } });
最後,PHP 這邊怎麼寫?
範例專案路徑與參考資料
Source code
* PHP Mongo DB Driver (需要裝到 apache/php 上)
* PHP CodeIgniter framework (包含在 project 裡)
到這裡你應該對 Mongo DB 有基本的認識
我想我們時間應該也不夠了 XDDDD
更實務一點的範例網站 XD
Ingress 鑰匙圈訂單系統
其中用 mongodb 進行的部份,包含
-
紀錄訂單與客製化細節
-
完成訂單時寄 email
-
使用者付錢時寄信來通知
-
後台查帳系統
- 使用者可以對訂單留言
我在這系統使用 mongo DB 的理由
- 客製化需要彈性,但彈性在 RDBMS 意味著多 table 與複雜 join 。
- 訂單本身跟其他資料通常是獨立的。
- schema 好開很多
-
修改或操作時可用 JS 操作,因此能額外作一些更精巧的控制。比起寫 SQL 的 store procedure /繞一圈用 php 處理,我更擅長寫 JS。
我猜這頁應該沒時間講完
mongodb 也有索引可以增加查詢效率。
mongodb 也可以用某些手段作到類似交易的 lock 機制,
但當然就會失去他部份效能作為代價。
mongodb 對於 not null 或之類的資料驗證是交給應用程式自己去管的,他最多只能設定 unique (不重複)這條件而已。
mongodb 可以寫 js 當成類似 stored procedure 用。
誠摯的忠告
千萬不要用 32bit 的 mongo DB,
因為資料超過 2G 就再也寫不進去了........
誠摯的忠告 2
-
如果你很熟悉 RDBMS,不要急著類比他們,因為你會撞牆。在 RDBMS裡面 Query 很昂貴(因為 lock /交易),但 NoSQL 裡面 Query 相對成本低很多。
- MongoDB 沒有 join,join 也不是他的強項,手動 merge 可以做到類似 join 的效果,效能也不算太差,但就是麻煩很多。
- 注意 document 跟 document 之間的單元性,千萬不要害怕資料重複(這點跟 RDBMS 的準則剛好相反),但要算好跟把握好每個不同資料的更新成本。
誠摯的忠告 3
如果你不是 NoSQL 專家、沒有 NoSQL 經驗,
請不要一頭熱的把重要的專案的 RDBMS 全部換成 No-SQL。
可以針對某些適合的部份,
局部上 NoSQL 在伺服器端互相合作或從小專案開始。
NoSQL 在實務上使用因為跟 RDBMS 要注意的細節很不一樣,直接跳過來往往都會在效能面發現自己思慮不周的部份。
誠摯的忠告 4
用 RDBMS 的思維寫 NoSQL 真的會很辛苦。我第一次用 mongo 就是用 SQL 要搬過來的觀念,不到兩週我就叛逃整組改回去用 mysql 了。
但後來再次運用在專案上,我完全只思考 mongo 該怎麼用,而不管 RDBMS 該怎麼用,用 mongo 就有如神助一樣。
回到原題,
為什麼要對 JavaScript developer 介紹 Mongo ?
因為最能作為一個使用者而掌握 Mongo 的,
當然就是對 JavaScript 最瞭解的 JS developer。
難得我們有機會比專業 DBA 還靠近 DB 核心呢,
我寫 mongo server side JS function
絕對比寫 store procedure 有信心不少。XD
而且就跨業整合來看, JavaScript 開發者實在不用自我設限。
時間有限,還有很多東西沒辦法提
但底下這些指令你實際去寫一定會碰到。
Query operation :
$in, $gt ($gte), $lt ($lte), $ne , $push , $pop
更新時 $upsert 也非常常用。
map-reduce
---------------------------------------------------------------------------------------
另外 Query 沒有限定你只能搜尋第一層的元素,
你可以搜尋任意層的子元素,只是表達式有點複雜。
ex.
db.messages.find({"replied.name":"Guest1" })
//搜尋 document 有 replied 成員,
//且這成員陣列中有 name 是 guest1 的物件。
Question ?
歡迎提問~~
Thanks
Mongo DB
By TonyQ Wang
Mongo DB
A slide to introduce mongo DB to javascript developers.
- 5,730