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 進行的部份,包含 
  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 就再也寫不進去了........




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