More Related Content Similar to MongoDBを用いたソーシャルアプリのログ解析 〜解析基盤構築からフロントUIまで、MongoDBを最大限に活用する〜 Similar to MongoDBを用いたソーシャルアプリのログ解析 〜解析基盤構築からフロントUIまで、MongoDBを最大限に活用する〜 (20) More from Takahiro Inoue (20) MongoDBを用いたソーシャルアプリのログ解析 〜解析基盤構築からフロントUIまで、MongoDBを最大限に活用する〜1. MongoDBを用いたソーシャ
ルゕプリのログ解析
〜解析基盤構築からフロントUIまで、
MongoDBを最大限に活用する〜
doryokujin
第1回 MongoDB JP & CouchDB JP 合同勉強会 in Tokyo
2. 自己紹介
• [自己紹介]
▶ いのうえ たかひろ( twitter: doryokujin )
▶ 福沢諭吉大学院2年、数学科 25歳
▶ マラソンも好き(ベスト2時間33分)
• [活動]
▶ MongoDB JP 主催者、ドキュメント訳者
▶ ブログ
▶ 芸者東京エンターテンメント GTE
▶ ゕルバト4ヶ月目、ログ解析部隊(1人)
3. 本日のゕジェンダ
1. ログ解析と MongoDB
▶ なぜ MongoDB を採用したか
2. ソーシャルゕプリのログ解析
▶ 解析バックエンドとフロントエンドでの MongoDB 活用例
3. MongoDB その他のトレンド
▶ MongoDB の先進的な活用事例:Logging、Hadoop、
Graph
5. ソーシャルゲームのログ解析
〜GTEの場合〜
• [目的] (もちろん会社によって様々)
‣ 今まで出ていた基本的なデータより、もっと細かく多
くのデータを提供する
‣ 明確に取得して見たいデータに加えて、あらゆるデー
タをとりあえず色々見てみる
‣ 解析のバックエンド(後述)からフロントエンドまで
を1人でやる
‣ 解析の結果自身が意志決定を行うのでは無く(機械学
習・高度な統計は不必要)、人間の意志決定を支援す
るための結果を出す
6. 解析バックエンドと
フロントエンド
‣ 一言に解析の仕事と言ってもバックエンドとフロントエンドで
全く異なる仕事になる
‣ 散在するログの収集に始まり、ゕナリスト(フロントエンド)
がいつでも所望のデータを取り出せるように適切な形式・場所
に格納するための基盤を構築するのがバックエンド
‣ 解析ツールを駆使し、また様々な視点でデータを解析し、人間
の意志決定を支援するための結果を導くのがフロントエンド
‣ バックエンドはンフラ、大規模分散処理技術・DB(RDB・
NoSQL)の知識が必要。規模や目的に合わせた設計が重要。と
ても泥臭い仕事
‣ フロントエンドの解析者はいつでもデータが取り出せるという
前提のもと、バックエンドを気にせず解析に専念できる状況を
想定している
7. ソーシャルゲームの行動ログ
• [行動ログ]
‣ 個々のユーザーの行動を詳細に知ることができる
‣ ユーザーの行動をいつ・何を・どのような形式でログ
に出力するのかは開発側が判断・決定
• [出力例]
‣ ログンした
‣ スタミナが 100 回復した
‣ ユーザー A のおみせからゕテム I を勝った
‣ ユーザー B に勝ってゕテム J をゲット
‣ ユーザー C の掲示板に書き込んだ
9. ソーシャルゲームの行動ログ
• [行動ログ詳細] 行動タプ ※行動の詳細の値は
[actionType] 様々:頻度・変化・
-----Change------ 対象・複合要素
ActionLogger a{ChangeP} (Point,1371,1383)
ActionLogger a{ChangeP} (Point,2373,2423)
------Get------
※行動タプごとに
ActionLogger a{GetMaterial} (syouhinnomoto,0,-1) 適切な整形が必要
ActionLogger a{GetMaterial} usesyouhinnomoto
ActionLogger a{GetMaterial} (omotyanomotoPRO,1,6)
-----Trade-----
ActionLogger a{Trade} buy 3 itigoke-kis from gree.jp:00000 #逆からみれば売った事に
-----Make-----
ActionLogger a{Make} make item kuronekono_n
ActionLogger a{MakeSelect} make item syouhinnomoto
ActionLogger a{MakeSelect} (syouhinnomoto,0,1)
-----PutOn/Off-----
ActionLogger a{PutOff} put off 1 ksuteras 行動の詳細
[actionDetail]
ActionLogger a{PutOn} put 1 burokkus @2500
-----Clear/Clean-----
ActionLogger a{ClearLuckyStar} Clear LuckyItem_1 4 times
-----Gatcha-----
ActionLogger a{Gacha} Play gacha with first free play:わくわくおみせ服ガチャ
ActionLogger a{Gacha} Play gacha:わくわくおみせ服ガチャ
10. ソーシャルゲームのログ解析
• [行動ログ解析で重要なこと]
‣ どの項目が関係し合っていて、また後で重要になるかがわ
からないので全て取得しておきたい
‣ そのため解析過程において、ログの持つ情報や構造が失わ
れないことが重要
‣ 集約したログの情報を一元管理するデータサーバーが必要
• [解析データサーバー]
‣ ログから情報を抽出し、それを格納しておく仕組み
‣ 格納場所はDB・HDFS・デゖレクトリ(フゔル)等…
‣ 蓄積された解析データはゕナリスト(フロントエンド)が
取り出して解析を行う
11. 解析データサーバー
解析対象となるデー
情報量や構造を失わ
アクセスロ タは全て解析データ
ないように
グ サーバーに
行動ログ
解析データ
サーバー
ゲームセー
ブ
可視化
データ
ランキング
課金情報
登録日
バックエンド フロントエンド
解析
各種ログ
12. 解析バックエンド for GTE
解析フロント
エンド
Dumbo (Python +
Hadoop )整形・フゖ 全集計結果は
ルタリング・簡易集計 MongoDBに格納
Sharding×3
Replica Set×3
Server× 3 整形・集計データ
scribe でローカルの
HDFS上に格納
Thrift & PHP
Python Script
(API)
ゲームセー ランキング
アクセスロ
行動ログ ブ 課金情報
グ
データ 登録日
データセンター(ホステゖング Cassandra MySQL
13. 解析フロントエンド for GTE
Sleepy.Mongoose
ソーシャルデータ
ゕクセスログ(遷移データ)
WebUI
解析対象データ
GraphDB 解析ツール
14. 最適な解析データサーバー
とは?
‣ 解析過程でいかに情報量を失わせないかが重要
‣ しかし様々な要因によって満足な情報を持ったデータ
情報量 保存が行えない
各 DB:SQL、NoSQL
種 フゔル群:NFS、HDFS
ロ
グ
解析データ
サーバー
工程・時間
15. 最適な解析データサーバー
とは?
‣ 解析過程でいかに情報量を失わせないかが重要
情報量
‣ しかし様々な要因によって満足な情報を持ったデータ
保存が行えない
要因1:散在するログの
集約に時間がかかる
各 要因3:SQLならスキーマの制約 要因4:データの取
種 やファイル・テーブルが多く 得・表示に手間と時
ロ 複雑になる 間がかかる
グ
要因2:集計処理が 解析データ
複雑・時間がかかる サーバー
工程・時間
16. 解析データサーバーとしての
MySQL
[メリット] [メリット]
• ドラバの充実 • ゕプリ側との親和性
• ノウハウが多数蓄積 • 検索クエリの充実
• 安定動作 • JOINが可能
[デメリット] [デメリット]
• スキーマ制約 • 特に無し
• スケールがそこそこ
大変
バックエンド フロントエンド
17. 解析データサーバーとしての
Hadoop・HIVE・Pig
[メリット] [メリット]
• 大規模分散処理 • 特に無し
• 集計時にJOINが可能 [デメリット]
• 簡単なスクリプト言 • HDFSの信頼性に不安
語で記述ができる
• データ取得に手間
[デメリット]
• データの検索性が悪い
• 処理フローの管理
• フゔル管理が面倒
• 詳細な処理がやや面
倒(Hive・Pig)
バックエンド フロントエンド
18. 解析データサーバーとしての
Cassandra・HBase
[メリット] [メリット]
• スキーマフリー • 特に無し
• 高い Write 性能 [デメリット]
• スケーラビリテゖ • 検索クエリが貧弱
• ドラバの充実 • ンデックスはキーの
み
[デメリット]
• コマンドランでの手
• 特に無し 軽な操作ができない
(データのゕクセス
性)
バックエンド フロントエンド
19. 解析データサーバーとしての
MongoDB
[メリット] [メリット]
• スキーマフリー • コマンドラン操作の充実
• ドキュメント指向
• 豊富な検索クエリ
• ドラバの充実
• 完全ンデックスサポート
• Replica Sets
• REST・Node.js・ORMが充
• Auto Sharding 実
[デメリット]
[デメリット]
• HDD・メモリ消費
• 特に無し
• 動作が不安定
バックエンド フロントエンド
20. MongoDB が最適な理由
[メリット]
• スキーマフリー・ドキュメント指向
‣ MONGODB RIAUNLEASHED 2010
• 豊富な検索クエリ
‣ Creating, Updating and Deleting Document in
MongoDB
• コマンドラン操作の充実 (JavaScript)
‣ 必要な関数は定義して保存しておける
‣ 必要な時にすぐにデータを取り出し、見せることができる
→ データを見せながら会話ができる
21. MongoDB が最適な理由
[メリット]
• 完全なンデックスサポート
‣ あらゆる項目でデータの取得が高速(10億レコードでも
高速検索)
‣ Indexing and Query Optimizer (Aaron Staple)
• Replica Sets・Auto Sharding
‣ データのバックゕップが容易→解析者の負担が軽減
‣ MongoDB Replica Sets
‣ Kristina Chodorow's Blog ( Part1 Part2 Part3 )
‣ MongoDB Auto-Sharding at Mongo Seattle
24. おみせやさん
▶ 会員数累計300万を誇る弊社ソーシャルゕプリのGREE版
▶ ゕクセスログ12GB / 日、行動ログ5GB / 日
▶ MySQL + Cassandra + Scala ( Lift ) による実装
▶ MongoDB + GraphDB によるデータ解析
▶ gumiStudy#6 300万人が遊ぶソーシャルゕプリ「おみせ
やさん」の作り方 →ンフラ関連のおはなし
25. 過去の発表資料
#TokyoWebMining
• HadoopとMongoDBを活用したソーシャルゕプ
リのログ解析 [2010/09/26]
‣ 関連ブログ
‣ ※解析バックエンドの話
• MongoDBとAjaxで作る解析フロントエンド&
GraphDBを用いたソーシャルデータ解析
[2010/11/14]
‣ 関連ブログ
‣ ※解析フロントエンド + GraphDB ( Neo4j ) の話
27. ゕクセスの流れ
ランキング
主に4種類のデータ 課金情報
MySQL
が解析対象 登録日
ゲームセーブ
Webserver Appserver Cassandra データ(ユー
(nginx) (Tomcat) 18ノード ザーステータ
7台 27台 ス)
アクセスログ 行動ログ
Flash
Compose
Hosting Server Server
28. 解析バックエンド
解析フロント
エンド
Dumbo (Python +
Hadoop )整形・フゖ 全集計結果は
ルタリング MongoDBに格納
Sharding×3
Replica Set×3
Server× 3 整形・集計データ
scribe でローカルの
HDFS上に格納
Thrift & PHP
Python Script
(API)
ゲームセー ランキング
アクセスロ
行動ログ ブ 課金情報
グ
データ 登録日
データセンター(ホステゖング Cassandra MySQL
29. 前処理としてのHadoop
• データの整形
‣ MongoDB に格納するためにフォーマットの統一
• データのフゖルタリング
‣ 1日約1億レコードある行動ログの情報削減
→ 解析を進めていく上で判明した不要項目は読み飛ばし
1日1000万レコード程度に削減
• 簡単な集計
• 今後のデータ増大に備えて
‣ サービスが増えてもスケールゕウトできるように
30. Dumbo
• [説明] http://github.com/klbostee/dumbo
‣ Python + Hadoop = Flying Circus Elephant
‣ Last.fm で使用
‣ Hadoop Streaming を実行
‣ map/reduce の記述が楽
‣ 簡単な join もできる
‣ デバッグが容易
31. 行動ログ集計:Dumbo
• [例] Dumbo で Word Count
def mapper(key, value):
for word in value.split(): yield word,1
def reducer(key, values):
yield key,sum(values)
if __name__ == "__main__":
import dumbo
dumbo.run(mapper, reducer)
「wordcount.py」
dumbo start wordcount.py ¥
-hadoop /path/to/hadoop ¥
-input wc_input.txt -output wc_output
32. Dumbo
• [メリット]
‣ MapperとReducer、Combinerも1フゔルに記述可
‣ Hadoop Streaming のオプションを引継ぐ
‣ HDFS上のフゔルの操作も可能(fs -ls や –put 等)
‣ Hadoop オプションを指定しない場合は、以下のパプラ
ン処理となり、デバッグ容易
python wordcount.py map < wc_input.txt | sort | ¥
python wordcount.py red > wc_output.txt
33. Hadoop 処理
1.Map:
‣ レコード内の必要な項目のみを抜き出す
‣ 不要なレコードはフゖルタリング
‣ 集計対象となる部分の整形処理(頻度・変化量・対象・複合)
2010-07-26 00:00:02,446 INFO catalina-exec-483 ActionLogger – userId a{Make} make
item onsenmanjyuu
2010-07-26 00:00:02,478 INFO catalina-exec-411 ActionLogger – userId a{LifeCycle}
Login
オリジナルンプット userId をkeyに、行動詳細部分をJson整形
userId 2010-07-26 00:00:02,446 a{Make} {onsenmanjyuu:1}
userId 2010-07-26 00:00:02,478 a{LifeCycle} {Login:1}
userId 2010-07-26 00:00:02,478 a{GetMaterial} {omotyanomotoPRO:5}
userId 2010-07-26 00:00:02,446 a{putOn} {item:A,user:B}
マップからの出力
34. 行動ログ集計
2.Reduce:
‣ [簡易集計] 同じ行動タプはユーザー毎に集計
‣ [デバッグ] 異常値(システムエラー・不正行動)の判定
もここで行う
‣ 非数値は頻度集計・数値は合計
‣ 複合要素はそれに応じた集計
‣ [Output] 最終的な出力はMongoDB
‣ HDFS上にはセッションログが書き出される
35. MongoDB Collection
ユーザー毎・日付毎 デリー集計
課金情報
登録日 user_charge daily_charge
行動ログ
user_trace daily_trace
ユーザー
ステータス user_savedata daily_savedata
アクセス
ログ user_access daily_access
36. MongoDB Collection
ユーザー毎・日付毎 デリー集計
課金情報
登録日 user_charge daily_charge
行動ログ
user_trace daily_trace
ユーザー
ステータス user_savedata daily_savedata
アクセス
ログ user_access daily_access
37. 行動データ
• [例] ユーザー×日付×タプ:user_trace
> db.user_trace.find({date:"2010-11-
10”,actionType:"a{Make}",userId:”7777"}).forEach(printjson)
{
"_id" : "2010-11-10+7777+a{Make}",
"date" : "2010-11-10"
"lastUpdate" : "2010-11-11",
"userId" : ”7777",
"actionType" : "a{Make}", ユーザー・日付・
"actionDetail" : { 行動タプごと
"make item ksutera" : 3,
"make item makaron" : 1,
"make item huwahuwamimiate" : 1,
"make item ringoame" : 3,
…
行動タプによっ
ては配列や入れ子
}
の辞書が入る
}
38. 行動データ
• [例] 全ユーザー×日付×タプ:daily_trace
> db.daily_trace.find({date:{$gte:"2010-11-10”,$lte:”2010-11-20”},actionType:"a{Make}"}).forEach(printjson)
{
"_id" : "2010-11-10+group+a{Make}",
"date" : "2010-11-10",
"lastUpdate" : "2010-11-12",
"actionType" : "a{Make}", 11-10から11-20
"actionDetail" : {
までの範囲指定
"make item kinnokarakuridokei" : 615,
"make item banjo-" : 377,
"make item itigoke-ki" : 135904,
"make item wadaiko" : 40,
"make item ha-pu" : 11,
"make item ribontore-sunohigasa" : 13621
...
},
...
}…
39. 課金データ
• [例] ユーザー×日付×行動タプ:user_charge
// 11/10に最も課金してくれたユーザーTOP10
> db.user_charge.find({date:"2010-11-10"}).sort({totalCharge:-1}).limit(10)
.forEach(printjson)
{
"_id" : "2010-11-10+7777+Charge",
"date" : "2010-11-10",
"lastUpdate" : "2010-11-10",
"totalCharge" : 10000,
"userId" : ”7777",
"actionType" : "Charge",
"boughtItem" : {
"アクセサリーの素EX" : 13,
"コネルギー+6000" : 3, ユーザーごとに内
"アクセサリーの素PRO" : 20 訳が変わってくる
}
}
{…
40. 課金データ
• [例] 全ユーザー×日付×タプ:daily_charge
> db.daily_charge.find({date:"2010-11-10",T:"all"}).limit(10).forEach(printjson)
{
"_id" : "2010-11-10+group+Charge+all+all",
"date" : "2010-11-10",
"total" : 100000,
"UU" : 2000,
"group" : {
"わくわくポント" : 1000000,
"アクセサリー" : 1000000,
...
}, ゕテムのカテゴ
"boughtItemNum" : {
リ別の内訳
"料理の素EX" : 8,
"アクセサリーの素" : 730,
...
},
"boughtItem" : {
"料理の素EX" : 10000,
"アクセサリーの素" : 100000,
...
}
}
41. MongoDB Collection
ユーザー属性抽出
課金情報
登録日
ユーザーの登録日・最
user_registration 終ログン日・総課金
額・初課金日 etc…
行動ログ
属性で分類したカテゴ
リごとの内訳(人数・
user_category 課金額)etc…
ユーザー
ステータス
異常値:ex. システムエ
ラー・欠損値・不正行
user_error 動 etc…
アクセス
ログ
42. MongoDB Collection
ユーザー属性抽出
課金情報
登録日
ユーザーの登録日・最
user_registration 終ログン日・総課金
額・初課金日 etc…
行動ログ
属性で分類したカテゴ
リごとの内訳(人数・
user_category 課金額)etc…
ユーザー
ステータス
異常値:ex. システムエ
ラー・欠損値・不正行
user_error 動 etc…
アクセス
ログ
43. ユーザー属性データ
• [例] ユーザー毎の属性データ:user_registration
> db.user_registration.find({userId:”7777"}).forEach(printjson)
{
"_id" : "2010-06-29+7777+Registration", 課金額・期間・登
"userId" : ”7777" 録日等に応じてカ
"actionType" : "Registration", テゴラズ
"category" : {
“R1” : “True”, #直近1週間ログンしていない場合 = True
“T” : “ll” #プレ期間が長期のユーザー
…
},
“firstCharge” : “2010-07-07”, #初課金日
“lastLogin” : “2010-09-30”, #最終ログン日
“playTerm” : 94, #プレ期間
“totalCumlativeCharge” : 50000, #総合課金額
“totalMonthCharge” : 10000, #直近1ヶ月の課金額
…
}
44. 属性カテゴリデータ
• [例] 属性毎の内訳を計算:user_category
> var cross = new Cross() //ユーザー定義関数 user_registraton.c
//月額課金×プレ期間(退会ユーザー) atagory のタグご
> MCResign = cross.calc(“2010-10-08”,“MC”,1) とに集計する関数
課金/期間 0円(z) ~1000円(s) ~10000円(m) 10000円~(l) 合計
~1日(z) 50000 10 5 0 50015
~1週間(s) 50000 100 50 3 50153
~1ヶ月(m) 100000 200 100 1 100301
~3ヶ月(l) 100000 300 50 6 100356
3ヶ月~(ll) 0 0 0 0 0
//月額課金×プレ期間(現役ユーザー)
> MCNotResign = cross.calc("2010-10-08","MC",-1)
課金/期間 0円(z) ~1000円(s) ~10000円(m) 10000円~(l) 合計
~1日(z) 50000 10 5 0 50015
~1週間(s) 50000 100 50 3 50153
~1ヶ月(m) 100000 200 100 1 100301
~3ヶ月(l) 100000 300 50 6 100356
3ヶ月~(ll) 0 0 0 0 0
…
45. ゕクセスデータ
• [例] チュートリゕルページの離脱状況を確認:
daily_access
//ユーザー定義関数
daily_access から
> access = getAccessData(“tutorial”,“2010-12-01”)
“tutorial”を含むゕ
UU PATH ドレスの値でソー
10000 /playshop2-gree/tutorial/FirstTopPage トして表示
9500 /playshop2-gree/tutorial/Tutorial01Page
01Page、 8000 /playshop2-gree/tutorial/Tutorial02Page
04Page 7700 /playshop2-gree/tutorial/Tutorial03Page
に問題
7000 /playshop2-gree/tutorial/Tutorial04Page
4000 /playshop2-gree/tutorial/make/avatar
3800 /playshop2-gree/tutorial/Tutorial05Page
…
46. データを格納する時の
• [形式]
ポント
‣ どのコレクションも1レコードあたり「ユーザー×日付×
行動タプ」で統一
‣ デリー集計の場合は userId = “group”
‣ _idも”{userId}+{date}+{actionType}”で統一して
記述
• [メリット]
‣ ユーザー・日付・行動タプの3軸で集計できる
‣ 検索時、collection間で統一したクエリーで記述できる
‣ _idの明確なルール化で容易にレコード特定
48. 解析フロントエンド
Sleepy.Mongoose
ソーシャルデータ
ゕクセスログ(遷移データ)
WebUI
解析対象データ
GraphDB 解析ツール
49. WebUI
• [目的]
‣ 社員全員で共有できるようにWebでデータを公開
‣ 基本はデリーの課金・行動データを出力
‣ 社内ツールなので無駄な作り込みは不要
‣ 取得している全てのデータにゕクセス可能
‣ 要望に応じて柔軟に項目追加できる仕様
50. WebUI:検討した仕様
• ① MVC + MongoDB → Ming
• ② node.js + MongoDB → Mongoose
• ③ REST Interface + MongoDB →
sleepy.mongoose
51. WebUI:検討した仕様 ①
• ①:[MVC + Mongo]
‣ Djangoで実装
‣ スキーマを(ある程度)定義。Validation機能便利。
MongoDBとDjangoをシームレスに扱えるツールが充実:
‣ Python:pymongo
‣ Django :MongoEngine、Ming、MongoKit、Django-nonrel
‣ 参考になるページ
‣ Django and NoSQL, any ready-to-use library?
‣ Which Python API should be used with Mongo DB and Django
‣ MongoDB hearts Django? (Django NYC)
52. MVC+MongoDB
• [例] スキーマの使用例
from ming.datastore import DataStore
from ming import Session
from ming import Document, Field, schema
bind = DataStore('mongo://localhost:30000/playshop')
session = Session(bind)
db
class UserTrace(Document):
class __mongometa__:
session = session collection
name = ‟user_trace‟
_id = Field(str) #標準のBSONオブジェクトなら Field(schema.ObjectId)
userId = Field(str)
actionType = Field(str)
…
#trace.py として保存
53. MVC+MongoDB
• [例] スキーマの使用例
import trace
…
#Ming provides a standard attribute .m, short for “manager”
>>> trace.userTrace.m.find().first()
{ "_id" : "2010-11-10+38733015+a{Make}",
"date" : "2010-11-10"
"lastUpdate" : "2010-11-11",
"userId" : ”7777",
"actionType" : "a{Make}",
"actionDetail" : { "make item ksutera" : 3,…}
}
54. WebUI:検討した仕様 ②
• ②:[node.js + Mongo]
‣ サーバサド Java Script
‣ クラゕントのリクエストをサーバー側で実行して結果を返す
‣ Mongoose は数種ある中で代表的なサーバサドJSラブラリ。
‣ Node.js 内で動くJava Script Library
‣ 未実装部分もあるが、十分使える
‣ Hummingbird がMongoDB+node.jsを使用した実例
‣ 参考になるページ
‣ Node.js and MongoDB
‣ node.js + express + mongodb + mongoose を試してみた
‣ Real time ecommerce analytics with MongoDB at Gilt Groupe
55. node.js+MongoDB
• [例] もっとも簡単な例
var mongoose = require('mongoose/').Mongoose,
db = mongoose.connect('mongodb://localhost/playshop'),
Collection = mongoose.noSchema(‟user_trace',db);
Collection.find({„date‟:‟2010-11-10‟}).each(function(doc){
// do something
});
56. node.js+MongoDB
• [例] Modelを利用した例
var mongoose = require('mongoose/').Mongoose,
db = mongoose.connect('mongodb://localhost/playshop');
mongoose.load('./models/');
User = mongoose.get(‟UserRegistration',db);
var user = new User({userId :‟7777', totalCharge : 10000, …});
user.lastLogin = „2010-11-10‟; // change a key value
user.save()
User.find({„date‟:‟2010-11-10‟}).each(function(user){
// do something…
});
57. node.js+MongoDB
• [参考書籍]
•MongoDB Sag ja zu NoSQL
•Marc Boeker
•Dezember 2010
•220 Seiten, Softcover
•ISBN: 978-3-86802-057-1
•E-Book-ISBN: 978-3-86802-244-5
•Preis: 24,90 € / 25,60 € (A)
•eBook Preis: 16,00 €
• 7章に「MongoDB mit Node.js」
58. WebUI:検討した仕様 ③
• ③:[REST Interface + Mongo]
‣ HTTP GET/POSTリクエストでデータを受け取る
‣ sleepy.mongoose
‣ /db_name/collection_name/_command 形式でリクエスト
‣ 10genのエンジニゕ @kchodorow さんが作った純正ツール
‣ Pymongo、pyOpenSSL を内部的に使用
‣ 参考になるページ
‣ Sleepy.Mongoose: A MongoDB REST Interface
59. REST Interface + Mongo
• [例] 使用例
//server起動
> python httpd.py
…listening for connections on http://localhost:27080
//MongoDBに接続
> curl --data server=localhost:30000 'http://localhost:27080/_connect‟
//クエリー の例
> curl -X GET 'http://localhost:27080/playshop/daily_charge/_find'
> http://localhost:27080/playshop/daily_charge/_find?criteria={}&limit=10&batch_size=10
{"ok": 1, "results": [{“_id": “…”, ”date":… },{“_id”:…}], "id": 0}}
60. REST Interface + Mongo
• [例] 使用例
//細かい条件でリクエストが可能
>http://localhost:27080//playshop/daily_charge/_find?criteria={“date”:{$gte:”2010-11-
01”,”$lte”:”2010-11-13”}}&sort={“date”:1}&limit=100&batch_size=100
{"ok": 1, "results": [{"date": "2010-11-01", "_id": "2010-11-01+group+Charge+all+all", "group":
…},{…},…,”id”:1}
61. フロントは
sleepy.mongoose
• [結論] sleepy.mongoose を採用
‣ 最も手軽(基本実装1日で完了)
‣ Ajaxと併せて非同期通信
‣ 今回必要な検索条件は全て使用できる事を確認
‣ 1回のデータ量もそれほど大きくない
‣ MongoDBとHTMLを仲介するフゔルが不要
62. WebUI:テーブル・グラフ
• [テーブル]
‣ 日毎の集計値を表で出力したい
‣ 各項目でソートしたい
‣ できるだけ簡単に実装したい
‣ jQuery.DataTables
‣ 項目ごとのソート機能
‣ 表示数指定・ページネーション機能
‣ 検索機能
‣ 精錬されたデザン
‣ $(document).ready(function(){ $(’#tableArea').dataTable();
});
63. WebUI:テーブル・グラフ
• [グラフ]
‣ データの可視化
‣ 主に時系列チャート
‣ できるだけ簡単に実装したい
‣ jQuery.HighCharts
‣ 多数のグラフが用意されている
‣ 精錬されたデザン
‣ ンタラクテゖブなグラフも可能
‣ ドキュメントが充実
64. WebUI:まとめ
Sleepy.Mongoose
JSON jQuery
• データ取得・描画がJSON形式でほぼダレクトに
やりとり
• 非常に手軽かつ高性能
65. WebUI:実例
‣ デリーの全ての課金内訳、行動内訳が閲覧可能
‣ CSVダウンロードリンク
‣ 特定のユーザーの課金、行動履歴を全てトラッキング可能
‣ 属性ごとのユーザー数内訳、分布
70. ログ解析 + MongoDB:
ベストプラクテゖス
• [まとめ]
‣ 3ゲーム・計500GB・10億レコードでも余裕
‣ スキーマレスかつ検索クエリが豊富なのが強い
‣ 自前スクリプトも定義でき、コンソールから様々な操作が
できる
‣ データの増加に対しても容易にスケールできる
‣ 解析目的では、コレクション数やンデックス対象になる
項目がそれほど多くない
73. Log to MongoDB
• Logging Application Behavior to MongoDB
‣ ゕプリケーションのログを中央管理できる
‣ フゔルの場合と比べてリモートでゕクセスしやすい
‣ ドキュメント指向と相性がよい。(フゔルログの各
項目をキーに、値をバリューにできる)
‣ スキーマレスなので様々なログ形式に対応
‣ ンデックスと豊富なクエリーを活用
‣ Capped collection がこの用途において非常に効果的
‣ JavaScript MapReduce によってデータ集約が可能
74. Log to MongoDB
• [Capped Collection]
‣ 固定サズのコレクション(古いデータから削除される)
‣ insert処理に特化、非常に高パフォーマンス(update処理
不可)
‣ ンデックス無・検索結果はinsert順(log tailing)
• [JavaScript Map Reduce※]
‣ MongoDB の Map Reduce、JavaScript で記述
‣ Sharding 間でスケールが可能
※現在1つのmongodプロセスでのMapReduce処理はシングルスレッドの制約がある
75. 解析バックエンド(今)
解析フロント
エンド
Dumbo (Python +
Hadoop )整形・フゖ 全集計結果は
ルタリング MongoDBに格納
Sharding×3
Replica Set×3
Server× 3 整形・集計データ
scribe でローカルの
HDFS上に格納
Thrift & PHP
Python Script
(API)
ゲームセー ランキング
アクセスロ
行動ログ ブ 課金情報
グ
データ 登録日
データセンター(ホステゖング) Cassandra MySQL
76. 解析バックエンド(案)
ゲームセー
ブ RealTime
データ
capped collection Update/hour
user_savedata
JavaScript
MapReduce
アクセスロ
capped collection Update/hour
グ user_access
RealTime
Modifier
Operations
capped collection Update/hour user_trace
行動ログ
RealTime
Python Script
ランキング
課金情報
MySQL 登録日
79. MongoDB + Hadoop
• [Hadoop]
‣ github: mongo-hadoop
‣ 現在は Java ドラバのみ
‣ Hadoop の入力として MongoDB のコレクションを指
定できる
‣ Hadoop の出力先にも MongoDB のコレクションを指
定できる
‣ MongoDB 独自のJavaScript MapReduce より柔軟で
強力な大規模分散処理が可能になる
80. MongoDB + Hadoop
• [Pig]
‣ 現在は MongoDB を出力先でのみ指定可能
‣ 将来的には入力先でも指定可能になる予定
-- Use the PigStorage function to store the results.
--Output:(hour, n-gram, score, count, average_counts_among_all_hours)
> STORE ordered_uniq_frequency ¥
INTO ’mongodb://localhost/test.pig.output‟ ¥
USING com.mongodb.hadoop.pig.MongoStorage;
> db.pig.output.find()
{
"_id" : ObjectId("4cbbbd9487e836b7e0dc1052"),
"hour" : "07”, "ngram" : "new”,"score" :2.4494897427831788,
"count" : NumberLong(2), "mean" : 1.1428571428571426
}
81. MongoDB + Hadoop
• [Flume]
‣ Sink (出力先)に MongoDBを指定可能
‣ github: mongo-fadoop/flume_plugin
Mongo
DB
Flume User Guide
(changed)
83. グラフ構造データ解析
• [グラフ構造を持ったデータ]
‣ ノードとエッジとその属性値で表現できるような構造
を持ったデータ
‣ ソーシャルデータ:TwitterのFollow関係、mixiのマ
ミク関係
‣ ゕクセスログ:ページ間の遷移データ・コンバージョ
ン
‣ リコメンドエンジンで使用するデータ
‣ その他多くのデータが実はグラフ構造で表現可能
84. グラフ構造データ解析
• [特殊な検索方法]
Building a Social Network with MongoDB
85. グラフ構造データ解析
• [特殊な検索方法]
‣ 近傍検索(友達の友達を探索)
> SELECT ?person WHERE {
?person KNOWS ?friend
?friend KNOWS ?classmate
?classname name “Takahiro Inoue”
}
‣ 重み付け検索(エッジの属性値で重み付け)
‣ こういった検索を GraphDB 以外でやるのは面倒
MongoDBとAjaxで作る解析フロントエンド&GraphDBを用いたソー
シャルデータ解析 (from 55 page)
86. グラフ構造データ解析
• [MongoDB でグラフ構造を扱う]
‣ Building a Social Network with MongoDB
‣ MongoDB でソーシャルデータの解析方法を述べたチ
ャレンジングな資料
‣ 近傍のデータを配列に格納、$in で検索可能に
‣ 工夫次第でグラフデータの解析も
‣ しかし、パフォーマンスは不明、かつレコードの保存
形式が複雑になる場合も
88. 今後の活動
• [解析者の存在価値を高めて行きたい]
‣ 到来する”BigData”の時代において、解析者が非常に
重要な存在になっていく事を証明していきたい
‣ それは自分の居場所をかけた戦いでもあり…
‣ 解析バックエンドを担える人は非常に重要。そしてそ
の強力な武器となるのがHadoopやNoSQL
‣ MongoDBと出会いで色んな可能性が見えてきた
‣ なのでMongoDBやデータ解析の話をさせてくれる機
会があればいつでも声をかけて下さい
89. ‣ 10gen
‣ MongoDB Documentation
‣ mongodb-user
‣ MongoDB JP
‣ CouchDB JP
‣ nosql-ja
ありがとうございました