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 

http://en.wikipedia.org/wiki/BSON

So what ?


他的內建查詢介面、內建預存函式的寫法

100%  JavaScript 


http://docs.mongodb.org/manual/tutorial/store-javascript-function-on-server/

資料庫還有分寫法?


不是開 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


http://www.mongodb.org/downloads
是獨立服務、會佔用一個 Port

認真用的一定要用 64 bit OS裝 64 bit 版,不然你一定會後悔。

另外注意:Data Folder
Window 安裝方法
Mac 安裝方法
Linux 相關安裝方法

安裝 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 
https://github.com/tony1223/mongodb-php-messageboard-sample/tree/nest-message 

回應怎麼存?


{
  "_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
https://github.com/tony1223/mongodb-php-messageboard-sample
* PHP Mongo DB Driver (需要裝到 apache/php 上)
http://docs.mongodb.org/ecosystem/drivers/php/
* PHP CodeIgniter framework (包含在 project 裡)
http://ellislab.com/codeigniter
https://github.com/alexbilbie/codeigniter-mongodb-library/tree/v2




到這裡你應該對 Mongo DB 有基本的認識
我想我們時間應該也不夠了 XDDDD

更實務一點的範例網站 XD


Ingress 鑰匙圈訂單系統
http://ingress.tw/order/new

其中用 mongodb 進行的部份,包含 
  1. 紀錄訂單與客製化細節
  2. 完成訂單時寄 email 
  3. 使用者付錢時寄信來通知
  4. 後台查帳系統
  5. 使用者可以對訂單留言


我在這系統使用 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 就再也寫不進去了........

http://blog.mongodb.org/post/137788967/32-bit-limitations



誠摯的忠告 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