2015年1月21日 星期三

[C++] JSON Library - jsoncpp @ Ubuntu 14.04, Mac OS X 10.10.1

JSON Format 現今已經是一個非常常見的溝通管道,最近常在 Ubuntu server 上練習 C++,偶爾沒網路時也會想用 Mac OS X 進行,因此,著重在如何輕鬆管理 C++ JSON Library 的用法,找了一下,大概就是 jsoncpp 啦

在 Ubuntu 14.04:

$ sudo apt-get install libjsoncpp-dev
$ g++ -I/usr/include/jsoncpp/ main.cpp -ljsoncpp


在 Mac OS X 10.10.1 搭配 MacPorts 管理:

$ sudo port install jsoncpp
$ g++ -std=c++11 -I/opt/local/include/ -L/opt/local/lib main.cpp -ljsoncpp


由於都可以透過系統常見的管理工具安裝,即可省去下載 source code 編譯等管理成本。簡易範例:

$ vim example.cpp
#include <iostream>       // std::cout
#include <string>         // std::string
#include <json/json.h>

int main() {
        std::string raw = "{\"key\":\"value\",\"我\":\"是誰\",\"array\":[\"a\",\"b\",123]}";
        Json::Reader reader;
        Json::Value value;
        std::cout << "Input: " << raw << std::endl;
        if (reader.parse(raw, value)) {
                std::cout << "parsing: " << value ;//<< std::endl;
                std::cout << "get: " << value["我"] ;//<< std::endl;
                std::string data = value["key"].asString();//toStyledString();
                std::cout << "string: [" << data << "]" << std::endl;

                // with -std=c++11
                std::cout << "---" << std::endl;
                for (auto it : value) {
                        std::cout << "elm: " << it ;//<< std::endl;
                        if (it.isArray()) {
                                for (auto it2 : it)
                                        std::cout << "array data: " << it2 ;//<< std::endl;
                        }
                }        
        }
        return 0;
}
$ g++ -I/opt/local/include/ -L/opt/local/lib main.cpp -ljsoncpp
$ ./a.out
Input: {"key":"value","我":"是誰","array":["a","b",123]}
parsing:
{
"array" : [ "a", "b", 123 ],
"key" : "value",
"我" : "是誰"
}
get: "是誰"
string: [value]
---
elm: [ "a", "b", 123 ]
array data: "a"
array data: "b"
array data: 123
elm: "value"
elm: "是誰"

2015年1月8日 星期四

[MySQL] 使用 FOREIGN KEY 筆記 @ MySQL 5.6

話說,2014年算是我最常用 SQL DB 的一年,在這之前我都是用 NOSQL 架構 Orz (扣除 SQLite 啦)。最近設計一些新服務的資料儲存,正在想如何使用 MySQL Relations 的特色,才發現之前都沒在用 FOREIGN KEY 啦 :P

簡短介紹 FOREIGN KEY 的功用:

當設計很多階層性的 table 時,如 user (上層), group (中層), data (下層),其中 data 每一筆都有 user, group 資訊,而 group 裡每一筆都跟 user 有關。此時在 DELETE 事件發生時,如果有建立 Relations 時,可在上層資料刪除時,順便幫你把相關資料刪掉。此外,在新增下層資料時,也會幫你驗證資料的正確性,不會讓你隨意新增假資料。

對於要建立 FOREIGN KEY 的要件:
  • 在上層(Parent)預計使用的參考欄位要有 index 屬性,如 Primary Key, Unique Key 或 Index 都行
  • 在下層(Child)預計使用的欄位也要有 index 屬性
  • 在上層跟下層對應的欄位型態要一樣,例如一樣為非負整數等
此外,則是可以設定 Action,例如上層刪除、更新資料時,下層是否也要一同更新,其選項:
  • Restrict: 拒絕 parent event,也將造成 parent 動作失敗
  • Cascade: 跟著 parent event 更新或是刪除
  • Set null: 收到 parent event 時,將參考欄位設定成 null
  • No action: 標準 SQL 語法且為預設選項,在 MySQL 環境上與 Restrict 等價
下次是操作時碰到的問題:

Q: Cannot add foreign key constraint
A: 仔細確認一下指定的欄位,其型態是不是一致的,或是對應的 Action 若為 Set Null 時,要確認資料欄位是否允許 Null

Q: Cannot add or update a child row: a foreign key constraint fails
A: 追蹤一下已存在的資料,是不是有不合理的地方,例如下層存在一筆資料,其對應上層的資料無法匹配。解法就是手動修正,或是乾脆清光資料來做也行。

整體上,建議有參考關係時,可以面對 Parent delete event 時,可以設定成 Cascade 處理,如此一來刪除資料就輕鬆許多,不必做多個處理。

2015年1月2日 星期五

MongoDB 開發筆記 - 替 Mongoose (Node.js MongoDB Driver) 送 patch 的經驗

大概 2014 年 11 月附近,下了班仍會抽空把玩 MongoDB ,當時就決定搭配 node.js 來把玩 :P 當時在挑選 Node.js MongoDB Driver 時,看到官方文件提到了 Mongoose ,就順勢把玩了幾下。

對於 nodejs - mongoose 跟 nodejs - mongodb 的差異點在於 mongoose 做了滿多整合方式,例如 QueryStreams 的效果,在處理大量資料時,非常便利!

除了適應 node.js 的 async 架構外,又發現 mongoose 跟原生 mongodb 設計上已經有些 out of date,在 Stack Overflow 和 mongoose issue 有不少抱怨,就試著 trace mongoose 架構,再送看看 patch,很幸運地被接受了 :P 而且只多寫了 2~3 行 code,果真好的 framework 都已經設計的很好,可能花了 15 分鐘了解架構,而 testing 花了 30 分鐘,結果 coding 才 3 分鐘 XDD

只是送 patch 的過程並沒有很順利,包含未先讀 mongoose / CONTRIBUTING.md 的描述就直接上 code,被挑了 coding style 問題,另外,還沒有跑 unit test XDDD 就碰到 CI 回報錯誤 Orz 接著才發現補上的那段 code 並不嚴謹。把 code 嚴謹化後,CI 也直接回報可以 merge :) 就這樣非常快地 2 天內就被 merge 進 master 了。

這次 patch 經驗:

  • 開發上碰到需求不被滿足,接著搜尋 Stack Overflow 及該專案的 issue tracking,發現問題一直沒被解決時,就可以著手看看要不要抽時間來貢獻
  • 接著發現解法後,一定要先看專案的 CONTRIBUTING 規定
  • 不錯的專案一定都有 unit test,記得跑一下
  • 提供簡單的 testing 程式碼跟預期結果,可以加速 commiter 閱讀及提升認同感

剩下的就只要花時間等待了 Orz 例如這次的 commiter 是 MongoDB New York RD,作息剛好日夜顛倒,因此每一次完整的互動大概都花了 2 天。

2014年12月29日 星期一

MongoDB 開發筆記 - 使用 MapReduce 進行 Matrix Multiplication (矩陣乘法) 運算

最近下了班有空時都會繼續專研 MongoDB 分析資料的部分,一開始完全都用 Aggregation ,實在是有一些實測的效能比 MapReduce 好很多,但對於一些較複雜的計算方式,一直用 Aggregation 反而會卡住或是增加資料結構的複雜度 Orz 總之,開始正式去寫一些簡單的 MongoDB MapReduce 程式。

把玩的過程中,發現先前設計的 Sparse Matrix 結構,在計算矩陣相乘時,花了不少步驟並且效果變成永遠只能有一隻 Mapper 在進行 Orz 完全不能平行處理,因此開始研究一下如何用 MapReduce 進行矩陣運算。

網路上資源果然豐富,找到一篇:Programming Puzzle: Multiply Matrixes with MongoDB,概念解釋得很清楚。簡言之,當矩陣相乘時,以 A x B = C 為例,在組成 C 矩陣內的元素過程中,會採用 A 跟 B 矩陣內的部分元素相乘,那麼試著找個關係式子,讓這些元素最後在 Reducer 裡撞在一起,撞在一起時再相乘即可。

原來如此簡單的想法就可以讓 MapReduce 架構處理矩陣相乘了!有興趣可以再參考一下:changyy/node-mongodb-matrix-multiplication

2014年12月28日 星期日

MongoDB 開發筆記 - 在 MapReduce 進行 debug 的一些心得

有點久沒寫 blog 了!最近有空時就是把玩 MongoDB 或是嘗試送一些 patch ,所以反而就少寫一些筆記,因為都改成用 Code 啦 :P

最近玩 Mongodb MapReduce 時,碰到幾個問題跟需求:
  • 碰到 mongod Out of memory
  • 想要在 Mapper 跟 Reducer 輸出一些 console 訊息
其中 out of memory 的部分,經過 trace 後發現是內部 Mapper 實作的架構採用 C++ Map Structure 紀錄結果,累計處理完一百筆資料會輸出,但如果單一個筆 input 會產生極大數量的結果時,就會出現 out of memory,已經送了個鳥鳥的 patch 出去,就看 MongoDB Reviewer 決定如何 :P 畢竟這種現象也可以歸屬在使用者資料設計問題,為何讓一筆 input 產生巨量資料 XD

至於現況怎樣解套?若碰到 mongod crash 問題,先試試把 jsMode 打開吧!因為 jsMode = true 時,將採用 v8 engine 處理 mapper function,並且資料是直接輸出到 temp collection 的,可避開 out of memory 問題。

對於前期開發時,想在 Mapper 跟 Reducer 印出一些訊息時,此時不能直接用 console.log(obj),要改用 print(JSON.stringify(obj)) ,並且去翻一下 

/var/log/mongodb/mongod.log 吧!