2014/05/07
2013/03/08
メインサーバーをMongodbで、の検討結果
アプリゲームのDBを完全にMongodbでやろうとして
使っている方に聞いて見た。
推薦ポイント
・MySQLのHA Proxyが構成出来ない時。
・Auto fail overを使いたい。
・初期設計・開発等テーブル定義がゆるい時のテスト用(他社実績有りとのこと)・ApacheのログやMySQLに格納したある期間のログデータを突っ込んでMapreduce等で解析を行いたい。
・データを突っ込んでから時差をおいてデータを読み込んで良い場合。
非推薦ポイント
・容量が食い過ぎ。
すべての動作ログを残すというのもあるが70Gを用意してサービス開始3日で70%を超えたと。
・以前570Gを超えたところから動作が可笑しくなり700Gで制御不能になった。
・安易にSecondaryのHDDを増設したらPrimaryとのSyncで2日。
・今回のゲーム仕様に3回まで入力できるがあるが、TransactionがなくSyncの時差により4,5回まで入力できる事が普通にありえるとのこと(これは仕方ないかも)。
・ShardingがTuningがやはり難しく偏り過ぎて諦めた。
結果
3回までのもありMySQLがやはりやりやすいかと。
但し開発初期のときだけはMongoDBでやってみるのも有りかも。
使っている方に聞いて見た。
推薦ポイント
・MySQLのHA Proxyが構成出来ない時。
・Auto fail overを使いたい。
・初期設計・開発等テーブル定義がゆるい時のテスト用(他社実績有りとのこと)・ApacheのログやMySQLに格納したある期間のログデータを突っ込んでMapreduce等で解析を行いたい。
・データを突っ込んでから時差をおいてデータを読み込んで良い場合。
非推薦ポイント
・容量が食い過ぎ。
すべての動作ログを残すというのもあるが70Gを用意してサービス開始3日で70%を超えたと。
・以前570Gを超えたところから動作が可笑しくなり700Gで制御不能になった。
・安易にSecondaryのHDDを増設したらPrimaryとのSyncで2日。
・今回のゲーム仕様に3回まで入力できるがあるが、TransactionがなくSyncの時差により4,5回まで入力できる事が普通にありえるとのこと(これは仕方ないかも)。
・ShardingがTuningがやはり難しく偏り過ぎて諦めた。
結果
3回までのもありMySQLがやはりやりやすいかと。
但し開発初期のときだけはMongoDBでやってみるのも有りかも。
2013/03/05
MongodbImportで_id指定方法による速度比較
_idをObjectIDにするのが容量が少し小さくなるのは分かった。
Import速度も「id」をObjectIDにした方が少し早い。
(個人の感想です。)
| Collection | StorageSize | Index Size | Objects | lastExtentSize|時間|
| t_u_xxxxx | 118.18m | 8.67m | 279,767 | 35.88m |18秒|:_idをObjectIDにした
| t_u_xxxxx | 118.18m | 9.72m | 279,767 | 35.88m | 21秒|: _idをIntにした
Tue Feb 26 17:36:34 38700 12900/second
Tue Feb 26 17:36:37 11789661/41384982 28%
Tue Feb 26 17:36:37 79700 13283/second
Tue Feb 26 17:36:40 18608276/41384982 44%
Tue Feb 26 17:36:40 125800 13977/second
Tue Feb 26 17:36:43 22527263/41384982 54%
Tue Feb 26 17:36:43 152300 12691/second
Tue Feb 26 17:36:46 28148602/41384982 68%
Tue Feb 26 17:36:46 190300 12686/second
Tue Feb 26 17:36:49 34909096/41384982 84%
Tue Feb 26 17:36:49 236000 13111/second
Tue Feb 26 17:36:52 41360034/41384982 99%
Tue Feb 26 17:36:52 279600 13314/second
Tue Feb 26 17:36:52 imported 279767 objects
Tue Feb 26 17:57:11 37700 12566/second
Tue Feb 26 17:57:14 13105364/41384979 31%
Tue Feb 26 17:57:14 88600 14766/second
Tue Feb 26 17:57:17 16891567/41384979 40%
Tue Feb 26 17:57:17 114200 12688/second
Tue Feb 26 17:57:20 20338409/41384979 49%
Tue Feb 26 17:57:20 137500 11458/second
Tue Feb 26 17:57:23 23652004/41384979 57%
Tue Feb 26 17:57:23 159900 10660/second
Tue Feb 26 17:57:26 28414510/41384979 68%
Tue Feb 26 17:57:26 192100 10672/second
Tue Feb 26 17:57:29 32970858/41384979 79%
Tue Feb 26 17:57:29 222900 10614/second
Tue Feb 26 17:57:32 38888195/41384979 93%
Tue Feb 26 17:57:32 262900 10954/second
Tue Feb 26 17:57:32 imported 279767 objects
Import速度も「id」をObjectIDにした方が少し早い。
(個人の感想です。)
| Collection | StorageSize | Index Size | Objects | lastExtentSize|時間|
| t_u_xxxxx | 118.18m | 8.67m | 279,767 | 35.88m |18秒|:_idをObjectIDにした
| t_u_xxxxx | 118.18m | 9.72m | 279,767 | 35.88m | 21秒|: _idをIntにした
- CSV Import Log(_idをObjectIDにした)
Tue Feb 26 17:36:34 38700 12900/second
Tue Feb 26 17:36:37 11789661/41384982 28%
Tue Feb 26 17:36:37 79700 13283/second
Tue Feb 26 17:36:40 18608276/41384982 44%
Tue Feb 26 17:36:40 125800 13977/second
Tue Feb 26 17:36:43 22527263/41384982 54%
Tue Feb 26 17:36:43 152300 12691/second
Tue Feb 26 17:36:46 28148602/41384982 68%
Tue Feb 26 17:36:46 190300 12686/second
Tue Feb 26 17:36:49 34909096/41384982 84%
Tue Feb 26 17:36:49 236000 13111/second
Tue Feb 26 17:36:52 41360034/41384982 99%
Tue Feb 26 17:36:52 279600 13314/second
Tue Feb 26 17:36:52 imported 279767 objects
- CSV Import Log( _idをIntにした)
Tue Feb 26 17:57:11 37700 12566/second
Tue Feb 26 17:57:14 13105364/41384979 31%
Tue Feb 26 17:57:14 88600 14766/second
Tue Feb 26 17:57:17 16891567/41384979 40%
Tue Feb 26 17:57:17 114200 12688/second
Tue Feb 26 17:57:20 20338409/41384979 49%
Tue Feb 26 17:57:20 137500 11458/second
Tue Feb 26 17:57:23 23652004/41384979 57%
Tue Feb 26 17:57:23 159900 10660/second
Tue Feb 26 17:57:26 28414510/41384979 68%
Tue Feb 26 17:57:26 192100 10672/second
Tue Feb 26 17:57:29 32970858/41384979 79%
Tue Feb 26 17:57:29 222900 10614/second
Tue Feb 26 17:57:32 38888195/41384979 93%
Tue Feb 26 17:57:32 262900 10954/second
Tue Feb 26 17:57:32 imported 279767 objects
2013/02/28
条件がIndexにある場合とない場合のMapReduceの速度比較
- Object数:289,701
- sort key : u_id asc , level asc
- find: delete_flg = 0 (件数が多い方)
- チューニングなどはしてない
参考:1オブジェクト当たり500回ループする
1.INDEX:u_id asc、level asc で実施したとき。
ntoreturn:1 keyUpdates:0 numYields: 2983 locks(micros) W:6563 r:848342771 w:13221 reslen:143 720053ms
2.INDEX:u_id asc、 level asc、 delete_flg asc で実施したとき。
ntoreturn:1 keyUpdates:0 numYields: 2983 locks(micros) W:4156 r:830311738 w:9896 reslen:143 703717ms3.INDEX:delete_flg asc、u_id asc、level asc で実施したとき。
ntoreturn:1 keyUpdates:0 numYields: 2983 locks(micros) W:4137 r:806274333 w:9771 reslen:143 683357ms4.INDEX:u_id asc, level asc、delete_flgの条件なし
ntoreturn:1 keyUpdates:0 numYields: 2983 locks(micros) W:3972 r:859051680 w:10412 reslen:143 730575ms
2013/02/25
NestedのRegexの検索
以下のdocumentで"_id"の"ymd”で部分一致(2013-01-05%)の検索をしたかった。
{ _id :{ ymd: "2013-01-05 02", i_id:2}, value {...}}
{ _id :{ ymd: "2013-01-05 03", i_id:5}, value {...}}
(1)$regexでやってみたが、nestedのfieldに対して$regexは出来ない模様。
(2)仕方なく以下の様にして今回は検索した。
{ _id :{ ymd: "2013-01-05 02", i_id:2}, value {...}}
{ _id :{ ymd: "2013-01-05 03", i_id:5}, value {...}}
(1)$regexでやってみたが、nestedのfieldに対して$regexは出来ない模様。
- 以下の様に作って見たが全て失敗した。
db.collections_name.find({ '_id.ymd' : "/2013-01-05/"});
db.collections_name.find({ '_id.ymd' : {$regex : "/2013-01-05/" } } );
- _idだからと思い全てのフィールドで条件を付けてみたが失敗。
db.collections_name.find({ _id, {ymd : "/2013-01-05/", i_id : 5 } } );
db.collections_name.find({ _id, {ymd' : {$regex : "/2013-01-05/", i_id :5 } } );
- Regex自体の問題かと思い次の様にNestedされてないfieldでやったら検索出来た。
db.collections_name.find({ field_name : /おに/});
(2)仕方なく以下の様にして今回は検索した。
db.collection_name.find({'_id.ymd' : {$gte :'2013-01-05', $lte:'2013-01-05'}});db.collections_name.find({'_id.ymd' : {$gte :'2013-01-05 00', $lte:'2013-01-05 23'}});
2013/02/21
MongoDBのDateで検索する際の落とし穴
MongoDbはISODateとして残る。
javascriptのnew ISODate()で登録すると GMTで登録される。
#参考にGMTとUSTはグリニッジ標準時をご覧ください。
これをphpのstrtotime()とかで日付を取得して検索すると
GMTとJSTの+9時間の時差が出る。
参考にphp.iniに「date.timezone = Asia/Tokyo」があった。
例)
(1) new ISODate(2013-01-02 01:00:00) で登録
GMTで登録される。すなわち JST 2013-01-01 16:00:00である。
(2) 以下のようにphpで検索条件を作る。
$start_date = new MongoDate(strtotime('2013-01-02 00:00:00'));
array("_id" => array ('$gte'=>$start_date));
print( date('T Y-m-d H:i:s',$start_date->sec) ) ; -> JST 2013-01-02 00:00:00'と表示される。
上記(1)をmongoで見るとISODate("2013-01-01T01:00:00Z")のように見えるから
注意しないと間違ってしまう。
登録するときは+09:00した時間で登録するか
あるいは検索条件に−09:00にしないと。。
参考になるサイトをreferenceに貼っておく。
しばらくはphpでnew MongoDate()する際に以下の様にしてる。
javascriptのnew ISODate()で登録すると GMTで登録される。
#参考にGMTとUSTはグリニッジ標準時をご覧ください。
これをphpのstrtotime()とかで日付を取得して検索すると
GMTとJSTの+9時間の時差が出る。
参考にphp.iniに「date.timezone = Asia/Tokyo」があった。
例)
(1) new ISODate(2013-01-02 01:00:00) で登録
GMTで登録される。すなわち JST 2013-01-01 16:00:00である。
(2) 以下のようにphpで検索条件を作る。
$start_date = new MongoDate(strtotime('2013-01-02 00:00:00'));
array("_id" => array ('$gte'=>$start_date));
print( date('T Y-m-d H:i:s',$start_date->sec) ) ; -> JST 2013-01-02 00:00:00'と表示される。
上記(1)をmongoで見るとISODate("2013-01-01T01:00:00Z")のように見えるから
注意しないと間違ってしまう。
登録するときは+09:00した時間で登録するか
あるいは検索条件に−09:00にしないと。。
参考になるサイトをreferenceに貼っておく。
しばらくはphpでnew MongoDate()する際に以下の様にしてる。
$GMT_TimeZone = new DateTimeZone('GMT');
$start_date_Ymd = new MongoDate(
DateTime::createFromFormat('Y-m-d H:i:s',
date("Y-m-d 00:00:00", strtotime("-31 days")), $GMT_TimeZone)->getTimestamp() );
2013/02/20
mongodbはHDDの容量が大きい
わけが有り32bitOSでKPI取得ツールを作成して運用中。
が、1ヶ月も立ってないのにstorage sizeが200M超え(Rockmongoから確認)!!
MySQLからCSVにしたデータは何M(何十M?)のはずだが
MongoDBは結構食う。
急ぎで作った(かつ、知識もなかった)から
英字で10文字以上のフィールド名をそのまま利用したり
CSVからのImportなので年月日と時分秒をそのまま文字として保持してる部分はある。
が、それでも怪しいので一段落したら調べる。
2013/03/05追記
CSVファイル容量の約2.5倍のDataSizeを食う事が分かった。
上のようにField名の工夫をしてない、日付をStringとして格納、
_idをObjectIdではなく個別にしてするなどの理由はあるがそれでもよりサイズが大きい事がわかった。
【容量記録】
| 日付 |SIZE | StorageSize | DataSize | Index Size |Objects | CSV size |DataSize増減|
| 2013/02/20 |-| 200m程度 | - | - | - |- |
| 2013/02/21 |1000m程度|294.52m | 209.55m | 18.4m | -|23m | -|
| 2013/02/22 |1023.75m| 387.91m | 258.68m | 22.8m | 862,368 |19m|49.13m|
| 2013/02/25 | 1.5G | 513.77m | 375.49m | 33.8m | 1,248,860 |46m |116.81m|
| 2013/02/26 | 1.5G | 514.54m | 404.36m | 33.15m | 1,344,394 | 12m |28.87m|
| 2013/02/26※1 | 1.5G | 170.60m | 127.56m | 11.45m | 453,500 | - |-276.8m|
| 2013/02/26※2 | 1.5G | 288.78m | 227.88m | 20.12m | 733,270 | 41.4m |100.32m|
| 2013/02/27 | 1023.75m | 320.09m | 242.35m | 26.96m | 789,443 | 13.7m |14.47m|
| 2013/02/28※4 | 1023.75m | 365.41m | 261.58m | 29.73m | 864,312 | 12.2m |19.23m|
| 2013/03/01※3 | 1.5G | 355.66m | 260.32m | 51.85m | 840,641| 4m |-1.26m|
※1:02/26に不要と判断したcollectionを3つDropして、Importしないようにした。
| Collection | StorageSize | Index Size | Objects | lastExtentSize|
| log_rxxxx |166.64M | 13.8M | 571,957 | 48.45M |
| log_s_xxx |166.64M | 7.29M | 300,781 | 48.45M |
| t_c_xxxxx |10.6M | 0.58M | 18,246 | 8M |
※2:41.4mのCSVファイルを新規にimportして「_id」を指定する時としない時の容量を比較したが、
ObjectIDにしたほうが少し小さかった。
| Collection | StorageSize | Index Size | Objects | lastExtentSize|
| t_u_xxxxx | 118.18m | 8.67m | 279,767 | 35.88m |:_idをObjectIDにした
| t_u_xxxxx | 118.18m | 9.72m | 279,767 | 35.88m | : _idをIntにした
※3 約30万Objects程のcollectionに対してindexに_id以外に2パータンを追加した。
totalIndexSizeが37.55mだった。複数キーのindexはサイズも大きい!!
※4 2m程はupdateされるデータ、不要ログの削除処理を追加
が、1ヶ月も立ってないのにstorage sizeが200M超え(Rockmongoから確認)!!
MySQLからCSVにしたデータは何M(何十M?)のはずだが
MongoDBは結構食う。
急ぎで作った(かつ、知識もなかった)から
英字で10文字以上のフィールド名をそのまま利用したり
CSVからのImportなので年月日と時分秒をそのまま文字として保持してる部分はある。
が、それでも怪しいので一段落したら調べる。
2013/03/05追記
CSVファイル容量の約2.5倍のDataSizeを食う事が分かった。
上のようにField名の工夫をしてない、日付をStringとして格納、
_idをObjectIdではなく個別にしてするなどの理由はあるがそれでもよりサイズが大きい事がわかった。
【容量記録】
| 日付 |SIZE | StorageSize | DataSize | Index Size |Objects | CSV size |DataSize増減|
| 2013/02/20 |-| 200m程度 | - | - | - |- |
| 2013/02/21 |1000m程度|294.52m | 209.55m | 18.4m | -|23m | -|
| 2013/02/22 |1023.75m| 387.91m | 258.68m | 22.8m | 862,368 |19m|49.13m|
| 2013/02/25 | 1.5G | 513.77m | 375.49m | 33.8m | 1,248,860 |46m |116.81m|
| 2013/02/26 | 1.5G | 514.54m | 404.36m | 33.15m | 1,344,394 | 12m |28.87m|
| 2013/02/26※1 | 1.5G | 170.60m | 127.56m | 11.45m | 453,500 | - |-276.8m|
| 2013/02/26※2 | 1.5G | 288.78m | 227.88m | 20.12m | 733,270 | 41.4m |100.32m|
| 2013/02/27 | 1023.75m | 320.09m | 242.35m | 26.96m | 789,443 | 13.7m |14.47m|
| 2013/02/28※4 | 1023.75m | 365.41m | 261.58m | 29.73m | 864,312 | 12.2m |19.23m|
| 2013/03/01※3 | 1.5G | 355.66m | 260.32m | 51.85m | 840,641| 4m |-1.26m|
※1:02/26に不要と判断したcollectionを3つDropして、Importしないようにした。
| Collection | StorageSize | Index Size | Objects | lastExtentSize|
| log_rxxxx |166.64M | 13.8M | 571,957 | 48.45M |
| log_s_xxx |166.64M | 7.29M | 300,781 | 48.45M |
| t_c_xxxxx |10.6M | 0.58M | 18,246 | 8M |
※2:41.4mのCSVファイルを新規にimportして「_id」を指定する時としない時の容量を比較したが、
ObjectIDにしたほうが少し小さかった。
| Collection | StorageSize | Index Size | Objects | lastExtentSize|
| t_u_xxxxx | 118.18m | 8.67m | 279,767 | 35.88m |:_idをObjectIDにした
| t_u_xxxxx | 118.18m | 9.72m | 279,767 | 35.88m | : _idをIntにした
※3 約30万Objects程のcollectionに対してindexに_id以外に2パータンを追加した。
totalIndexSizeが37.55mだった。複数キーのindexはサイズも大きい!!
※4 2m程はupdateされるデータ、不要ログの削除処理を追加
2013/02/15
MongoDBのMapreduceの落とし穴(undefinedが発生する理由と対策)
1)Mapreduceで集計をしたらreduceの処理途中にundefineのレコードがあり、一部集計が失敗した。
不良データを探そうとprint()で_idで調べたら以下のような結果となり不良データがないように見えた。
Map/reduce : _id
map : 1
map : 2
map : 3
reduce : 1
reduce : 2
reduce : 3
map : 4
map : 5
reduce : undefine
reduce : 4
reduce : 5
原因と対策方法は時間があるときに探そう。
2つのCollectionを纏めてMapreduce方法を探していたら
http://tebros.com/2011/07/using-mongodb-mapreduce-to-join-2-collections/に
2)上は解決したが、それでも集計結果が不一致。
以下の_id : 3 が集計されない。reduceの実行のタイミング怪しい?
Map/reduce :_id : group key(break key?)
map : 1 : 2013-01-01
map : 2 : 2013-01-01
map : 3 : 2013-01-02
reduce : 1 : 2013-01-01
reduce : 2 : 2013-01-01
reduce : 3 : 2013-01-02
map : 4 : 2013-01-02
map : 5 : 2013-01-03
reduce : undefined : undefined ← reduce : 3までの処理結果
reduce : 4 : 2013-01-02
reduce : 5 : 2013-01-03
原因:map -> reduce→map -> reduceが繰り返し処理される。
この繰り返しの時、前のreduceの結果を引き継ぐためにreduceのValue[0]に前回の処理結果が渡される。
例えば
emit( key: {user_id : [this.user_id], count:1}
reduce(key,v) { var reducedValue = {u_id:[], t_c:0}; ... }
にしたとき
同じkeyの中で2回目に呼ばれたv[0]はreducedValueのu_idとt_cの配列が来る。
http://ryooo321.blogspot.jp/2012/05/mongodbmapreduce.html からヒントを頂きました。
*2013/02/19追記
6576件のデータを集計してみたが
600件ずつ集めて、Groupkeyが変更される前の時点で
600件の配列を10回、576件の配列が1回繰り返しの処理に入って来た。
{Key: 2013-02-17 、件数: 201件}
{Key: 2013-02-18 、件数: 6576件}
reduce -> 2013-02-17 :(100件 X 2回)+1件呼出す
reduce -> 2013-02-18 :(100件 X 6回) X10回+(100件 X 5回)+76件 呼出す
finalize -> 2013-02-17 :1回 呼出す
reduce -> 2013-02-18 : (600件 X10回)+ (576件X1回) 呼出す // 新しい配列
finalize -> 2013-02-18 :1回 呼出す
結論は、
mapのemitで指定するValueのIDの名称とreduceのIDの名称を一致させるべき。(マニュアルにあったけど理解出来なかった。)
良い例)
emit( _id , { u_id : this.user_id, t_c : 1})
reduce (k, v) {
var rValue = {u_id : "", t_c : 0};
rValue.t_c += v.t_c;
rValue.t_c += v.u_id + rValue.u_id;
return rValue;
}
悪い例)
emit( _id , { user_id : this.user_id, count : 1})
reduce (k, v) {
var rValue = {u_id : "", t_c : 0};
rValue.t_c += v.count; // undefinedが発生する可能性有り
rValue.t_c += v.user_id + rValue.u_id; // undefinedが発生する可能性有り
return rValue;
}
不良データを探そうとprint()で_idで調べたら以下のような結果となり不良データがないように見えた。
Map/reduce : _id
map : 1
map : 2
map : 3
reduce : 1
reduce : 2
reduce : 3
map : 4
map : 5
reduce : undefine
reduce : 4
reduce : 5
原因と対策方法は時間があるときに探そう。
2つのCollectionを纏めてMapreduce方法を探していたら
http://tebros.com/2011/07/using-mongodb-mapreduce-to-join-2-collections/に
if (this.FY2009 !== undefined && this.FY2009 !== null) {
のようなCodeがあった。2)上は解決したが、それでも集計結果が不一致。
以下の_id : 3 が集計されない。reduceの実行のタイミング怪しい?
Map/reduce :_id : group key(break key?)
map : 1 : 2013-01-01
map : 2 : 2013-01-01
map : 3 : 2013-01-02
reduce : 1 : 2013-01-01
reduce : 2 : 2013-01-01
reduce : 3 : 2013-01-02
map : 4 : 2013-01-02
map : 5 : 2013-01-03
reduce : undefined : undefined ← reduce : 3までの処理結果
reduce : 4 : 2013-01-02
reduce : 5 : 2013-01-03
原因:map -> reduce→map -> reduceが繰り返し処理される。
この繰り返しの時、前のreduceの結果を引き継ぐためにreduceのValue[0]に前回の処理結果が渡される。
例えば
emit( key: {user_id : [this.user_id], count:1}
reduce(key,v) { var reducedValue = {u_id:[], t_c:0}; ... }
にしたとき
同じkeyの中で2回目に呼ばれたv[0]はreducedValueのu_idとt_cの配列が来る。
http://ryooo321.blogspot.jp/2012/05/mongodbmapreduce.html からヒントを頂きました。
*2013/02/19追記
6576件のデータを集計してみたが
600件ずつ集めて、Groupkeyが変更される前の時点で
600件の配列を10回、576件の配列が1回繰り返しの処理に入って来た。
{Key: 2013-02-17 、件数: 201件}
{Key: 2013-02-18 、件数: 6576件}
reduce -> 2013-02-17 :(100件 X 2回)+1件呼出す
reduce -> 2013-02-18 :(100件 X 6回) X10回+(100件 X 5回)+76件 呼出す
finalize -> 2013-02-17 :1回 呼出す
reduce -> 2013-02-18 : (600件 X10回)+ (576件X1回) 呼出す // 新しい配列
finalize -> 2013-02-18 :1回 呼出す
結論は、
mapのemitで指定するValueのIDの名称とreduceのIDの名称を一致させるべき。(マニュアルにあったけど理解出来なかった。)
良い例)
emit( _id , { u_id : this.user_id, t_c : 1})
reduce (k, v) {
var rValue = {u_id : "", t_c : 0};
rValue.t_c += v.t_c;
rValue.t_c += v.u_id + rValue.u_id;
return rValue;
}
悪い例)
emit( _id , { user_id : this.user_id, count : 1})
reduce (k, v) {
var rValue = {u_id : "", t_c : 0};
rValue.t_c += v.count; // undefinedが発生する可能性有り
rValue.t_c += v.user_id + rValue.u_id; // undefinedが発生する可能性有り
return rValue;
}
2013/02/14
MapReduceのjavascriptのデバッグ方法
Mapreduceのjavascriptの処理の途中の値を見たいときは。
mongo シェルから実行するときは普通に
print("user_id =" + user_id);
のようにすればmongodのログに出力された。
PHPから実行したときは?
あとで確認する。
mongo シェルから実行するときは普通に
print("user_id =" + user_id);
のようにすればmongodのログに出力された。
PHPから実行したときは?
あとで確認する。
2013/02/08
TASK#2 PHPで年月日でGroup byしてカウントする方法
SELECT DATE_FORMAT( `create_date` , '%Y/%m/%d %H:00:00' ), COUNT(user_id) FROM user_table GROUP BY DATE_FORMAT(`create_date`, '%Y%m%d %H') の実装方法
(1)mapreduceでjavascriptのdateformatを使って文字列を日付に変換させようとしたが、次のエラーが出て失敗。
exception: map invoke failed: JS Error: ReferenceError: DateFormat is not defined nofile_b:1CSVでデータをImportしたときは
日付のGroup Byをしたい場合は「年/月/日/時/分/秒」等で分類して持った方がやりやすいかも。
(2)Mapreduce関数を利用した(Scopeも利用した)
// get yyyyMMddのScope機能も利用 $scopeFunction = "function (y,m,d) { if ( m < 10) {m = '0' + m;} if ( d < 10) {d = '0' + d;} return y + m + d; }"; $scope = new MongoCode($scopeFunction); // MongcodeでScopeを利用 // map 関数と reduce 関数を作ります $map = new MongoCode("function() { var group_key = getYyyyMMdd(this.create_date_y,this.create_date_m,this.create_date_d); emit(group_key,1); }"); //GroupByのcreate_dateになるキー $reduce = new MongoCode("function(k, vals) { var count = 0; // 初期化 for (var i in vals) { count += vals[i]; //count up } return count; }");
// phpのCommandで実行
$result = $db->command(array(
"mapreduce" => "collection",
"map" => $map,
"reduce" => $reduce,
"scope" => array("getYyyyMMdd"=>$scope), // この設定に注意
"out" => array("replace"=>"new_user_daily_count")
));
$cur_daily_counts = $db->selectCollection($result['result'])->find();
datetimeで範囲検索してカウントする
datetimeで範囲検索
検索のみ
db.user.find({create_date:{$gte:"2013-01-26 00:00:00",$lte:"2013-01-26 23:59:59"}})
カウント
db.user.find({create_date:{$gte:"2013-01-26 00:00:00",$lte:"2013-01-26 23:59:59"}}).count()
create_dateがdate型ではなかったが、String比較で抽出されたと思う。
検索のみ
db.user.find({create_date:{$gte:"2013-01-26 00:00:00",$lte:"2013-01-26 23:59:59"}})
カウント
db.user.find({create_date:{$gte:"2013-01-26 00:00:00",$lte:"2013-01-26 23:59:59"}}).count()
create_dateがdate型ではなかったが、String比較で抽出されたと思う。
2013/02/04
MongoDBを使う上の基本を勝手に決めてみた。
- Reference
http://docs.mongodb.org/manual/reference/ - About BSON Document
http://docs.mongodb.org/manual/core/document/ - MongoDB Extended JSON
http://docs.mongodb.org/manual/reference/mongodb-extended-json/
- Use Cases
http://docs.mongodb.org/manual/use-cases/
- SQL to MongoDB Mapping Chart
http://jp.docs.mongodb.org/manual/reference/sql-comparison/
- PHP Manual
http://www.php.net/manual/en/mongo.tutorial.php
登録:
投稿 (Atom)