MongoDBとAjaxで作る解析フロントエンド&GraphDBを用いたソーシャルデータ解析

16,758 views

Published on

Published in: Technology
2 Comments
30 Likes
Statistics
Notes
No Downloads
Views
Total views
16,758
On SlideShare
0
From Embeds
0
Number of Embeds
3,896
Actions
Shares
0
Downloads
216
Comments
2
Likes
30
Embeds 0
No embeds

No notes for slide

MongoDBとAjaxで作る解析フロントエンド&GraphDBを用いたソーシャルデータ解析

  1. 1. 明日から始めるログ解析② ~MongoDBとAjaxで作る解析フロントエンド &GraphDBを用いた解析事例紹介~ doryokujin 第8回 データマ゗ニング+WEB 勉強会@東京 (Tokyo.Webmining #8) -大規模解析・ウェブ・クオンツ 祭り-
  2. 2. 自己紹介 • [自分] ▶ いのうえ たかひろ( twitter: doryokujin ) ▶ 慶應大学院2年、数学科 25歳 ▶ MCMC、#P問題、近似ゕルゴリズム ▶ マラソンも好き(2時間30分位で走れてた) • [会社] ▶ 芸者東京エンターテ゗ンメント GTE ▶ ゕルバ゗ト3ヶ月目、ログ解析部隊(1人) ▶ おしごと非常に楽しいです
  3. 3. 最近の活動 • [MongoDB] ▶ MongoDB の日本語ドキュメント訳(Admin Zone) ▶ 進捗が遅くてすいません、勉強します、がんばります ▶ 勉強会とか、ユーザー会発足とか、もっと Mongo な活動 がしたい! ▶ ご意見・協力してくれる人、いつでも声をかけて下さい • [ブログ] ▶ 始めました ▶ 勉強会報告、MongoDB、GraphDBを中心に…
  4. 4. 発表の目的 • ソーシャルゕプリの裏側(ログ解析)の面白さ を伝えたい ▶ ダ゗ナミックで最高に面白い世界 • ノウハウを公開・共有することで、会社に、業 界の発展のために少し貢献できれば ▶ ほとんど着手できないところも多いはず ▶ 解析を始めるきっかけや、方法を利用していただければ ▶ そもそも社内で自分以外だれもわからないので外に出て行 くしかない ▶ 積極的に情報公開することによって得られるフゖードバッ クに期待
  5. 5. 本日のゕジェンダ 1. ログ解析バックエンド(前回の復習) ▶ 散在するデータを収集・集計するための基盤構築 ▶ [key] MongoDB、Hadoop、Dumbo 2. ログ解析フロントエンド ▶ MongoDBに格納したデータをどう表示するか ▶ [key] MongoDB、Ajax(jQuery)、ORM、node.js 3. 応用的な解析事例 ▶ デ゗リー集計以外にこんな面白い解析をやってます ▶ [key] おかねもちさん、GraphDB(Neo4j)、Gremlin
  6. 6. 1. ログ解析バックエンド ※データの数値は正しい値はないのでご注意下さい
  7. 7. おみせやさん ▶ 会員数累計300万を誇るソーシャルゕプリのGREE版 ▶ ゕクセスログ10GB、行動ログ4GB / 日 ▶ Scala+Lift+Cassandra ▶ gumiStudy#6 300万人が遊ぶソーシャルゕプリ「おみせ やさん」の作り方 →゗ンフラ関連のおはなし
  8. 8. 前回の資料 • HadoopとMongoDBを活用したソーシャルゕプ リのログ解析 ‣ 関連ブログ ‣ データをどう収集し、どこに集積させていくか ‣ 行動ログとはどのようなものであるか ‣ どういった視点で集計値を出していくか
  9. 9. Amazon S3にBack Up Flash Compose Server Cassandra 18ノード MySQL Webserver (nginx) 8台 Appserver (Tomcat) 18台 ゲームセーブ データ(ユー ザーステータ ス) アクセスログ ランキング 課金情報 登録日 行動ログ ゕクセスの流れ 主に4種類のデータ が解析対象
  10. 10. ランキング 課金情報 登録日 解析バックエンド 行動ログアクセスログ 社内データストレージ (S3と同期) ゲームセーブ データ MySQLCassandra 解析サーバー 3台 nfsでマウント Python Script Dumbo (Python + Hadoop )で集計処理 全集計結果は MongoDBに格納 Python Script フロントエンド 集計データ Sharding×3 Replica Set×2
  11. 11. 前処理としてのHadoop • データクリーニング機能として ‣ 1日約1億レコードある行動ログの情報削減 → 不要項目は読み飛ばし1日1000万レコード程度に削減 • 今後のデータ増大に備えて ‣ サービスが増えてもスケールゕウトできるように • 強力なソート機能の利用 ‣ 最終ログ゗ン日の計算などに有用
  12. 12. MongoDB Collection デ゗リー集計 user_charge 課金情報 登録日 行動ログ アクセス ログ ユーザー ステータス user_trace user_savedata user_access データ収集・格納 daily_charge daily_trace daily_savedata daily_access
  13. 13. MongoDB Collection デ゗リー集計 user_charge 課金情報 登録日 行動ログ アクセス ログ ユーザー ステータス user_trace user_savedata user_access データ収集・格納 daily_charge daily_trace daily_savedata daily_access
  14. 14. • [例] ユーザー×日付×タ゗プ:user_trace 行動データ > db.user_trace.find({date:"2010-11- 10”,actionType:"a{Make}",userId:”7777"}).limit(10).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, … } }
  15. 15. • [例] 全ユーザー×日付×タ゗プ:daily_trace 行動データ > db.daily_trace.find({date:"2010-11- 10",actionType:"a{Make}"}).limit(10).forEach(printjson) { "_id" : "2010-11-10+group+a{Make}", "date" : "2010-11-10", "lastUpdate" : "2010-11-12", "actionType" : "a{Make}", "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 ... }, ... }
  16. 16. • [例] ユーザー×日付×タ゗プ:user_charge 課金データ > 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, "アクセサリーの素" : 9, "アクセサリーの素PRO" : 20 } }
  17. 17. • [例] 全ユーザー×日付×タ゗プ: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, "group" : { "わくわくポ゗ント" : 1000000, "アクセサリー" : 1000000, ... }, "boughtItemNum" : { "料理の素EX" : 8, "アクセサリーの素" : 730, ... }, "boughtItem" : { "料理の素EX" : 10000, "アクセサリーの素" : 100000, ... } }
  18. 18. MongoDB Collection デ゗リー・ ウゖークリー集計 user_registration 課金情報 登録日 行動ログ アクセス ログ ユーザー ステータス user_category ユーザー属性抽出 user_error ユーザーの登録日・最 終ログ゗ン日・総課金 額・初課金日 etc… 属性で分類したカテゴ リごとの内訳(人数・ 課金額)etc… 異常値:ex. システムエ ラー・欠損値・不正行 動 etc…
  19. 19. MongoDB Collection デ゗リー・ ウゖークリー集計 user_registration 課金情報 登録日 行動ログ アクセス ログ ユーザー ステータス user_category ユーザー属性抽出 user_error ユーザーの登録日・最 終ログ゗ン日・総課金 額・初課金日 etc… 属性で分類したカテゴ リごとの内訳(人数・ 課金額)etc… 異常値:ex. システムエ ラー・欠損値・不正行 動 etc…
  20. 20. • [例] ユーザー毎の属性データ: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 … }, “firstCharge” : “2010-07-07”, #初課金日 “lastLogin” : “2010-09-30”, #最終ログ゗ン日 “playTerm” : 94, #プレ゗期間 “totalCumlativeCharge” : 50000, #総合課金額 “totalMonthCharge” : 10000, #直近1ヶ月の課金額 … }
  21. 21. • [例] 属性毎の内訳を計算:user_category 属性カテゴリデータ > var cross = new Cross() //ユーザー定義関数 //月額課金×プレ゗期間(退会ユーザー) > 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 …
  22. 22. 格納データ • [形式] ‣ どのコレクションもブロック当たり「ユーザー×日付×行 動タ゗プ」で統一 ‣ デ゗リー集計の場合は userId = “group” ‣ _idも”{userId}+{date}+{actionType}”で記述 • [メリット] ‣ ユーザー・日付・行動タ゗プの3軸で集計できる ‣ 検索時、collection間で統一したクエリーで記述できる ‣ _idの明確なルール化で容易にレコード特定可
  23. 23. 2. ログ解析フロントエンド
  24. 24. 解析フロントエンド WebUI Visualization Console 解析 Sleepy.Mongoose ソーシャル データ 解析 データ
  25. 25. 解析フロントエンド • [WebUI] ‣ 日毎の指標集計値を表示、可視化 ‣ 社員全員が閲覧し、共有できるもの ‣ 完全自動集計 • [解析] ‣ より詳細な解析を行うためのツール ‣ Rをメ゗ンに、Tableau、Bime を試験的に活用中…
  26. 26. WebUI • [目的] ‣ 基本的な指標集計値を社員全員で共有できるように ‣ デ゗リーの課金・行動データを全自動集計 • [ポ゗ント] ‣ 社内ツールなので無駄な作り込みは不要 ‣ 解析の深さよりも項目の種類重視 ‣ 要望に応じて柔軟に項目追加できる仕様
  27. 27. WebUI:検討した仕様 • ① MVC + MongoDB → Ming • ② node.js + MongoDB → Mongoose • ③ REST Interface + MongoDB → sleepy.mongoose
  28. 28. 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)
  29. 29. • [例] スキーマの使用例 node.js+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) class UserTrace(Document): class __mongometa__: session = session name = ’user_trace’ _id = Field(schema.ObjectId) userId = Field(str) actionType = Field(str) … #trace.py として保存
  30. 30. • [例] スキーマの使用例 node.js+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,…} }
  31. 31. 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
  32. 32. • [例] もっとも簡単な例 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 });
  33. 33. • [例] Modelを利用した例 node.js+MongoDB 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… });
  34. 34. WebUI:検討した仕様 • ③:[REST Interface + Mongo] ‣ HTTP GET/POSTリクエストでデータを受け取る ‣ sleepy.mongoose ‣ /db_name/collection_name/_command 形式でリクエスト ‣ 10genのエンジニゕ @kchodorow さんが作った純正ツール ‣ Pymongo、pyOpenSSL を内部的に使用 ‣ 参考になるページ ‣ Sleepy.Mongoose: A MongoDB REST Interface
  35. 35. • [例] 使用例 REST Interface + Mongo //server起動 > python httpd.py …listening for connections on http://localhost:27080 //MongoDbに接続 > curl --data server=localhost:30000 'http://localhost:27080/_connect’ //クエリー 2つは同じ結果をJSONで返す > curl -X GET 'http://localhost:27080/foo/bar/_find' > http://localhost:27080/playshop/daily_charge/_find?criteria={}&limit=10&batch_size=10 {"ok": 1, "results": [{“_id": “…”, ”date":… },{“_id”:…}], "id": 0}}
  36. 36. • [例] 使用例 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": [{"lastUpdate": "2010-11-02", "_id": "2010-11-01+group+Charge+all+all", "group": …},{…},…,”id”:1}
  37. 37. sleepy.mongoose • [結論] sleepy.mongoose を採用 ‣ 最も手軽(基本実装1日) ‣ Ajaxと併せて非同期通信 ‣ 今回必要な検索条件は全て使用できる事を確認 ‣ 1回のデータ量もそれほど大きくない ‣ MongoDBとHTMLを仲介するフゔ゗ルが不要
  38. 38. WebUI:テーブル・グラフ • [テーブル] ‣ 日毎の集計値を表で出力したい ‣ 各項目でソートしたい ‣ できるだけ簡単に実装したい ‣ jQuery.DataTables ‣ 項目ごとのソート機能 ‣ 表示数指定・ページネーション機能 ‣ 検索機能 ‣ 精錬されたデザ゗ン
  39. 39. WebUI:テーブル・グラフ • [グラフ] ‣ データの可視化 ‣ 主に時系列チャート ‣ できるだけ簡単に実装したい ‣ jQuery.HighCharts ‣ 多数のグラフが用意されている ‣ 精錬されたデザ゗ン ‣ ゗ンタラクテゖブなグラフも可能 ‣ ドキュメントが充実
  40. 40. WebUI:まとめ • データ取得・描画がJSON形式でほぼダ゗レクトに やりとり • 非常に手軽かつ高性能 JSON Sleepy.Mongoose jQuery
  41. 41. WebUI:実例 ‣ 日毎に全ての課金内訳、行動内訳が閲覧可能 ‣ CSVダウンロードリンク ‣ 特定のユーザーの課金、行動履歴を全てトラッキング可能 ‣ 属性ごとのユーザー数内訳、分布
  42. 42. WebUI:実例
  43. 43. WebUI:実例
  44. 44. WebUI:実例
  45. 45. 解析ツール • [R] ‣ フリーの統計解析ソフト ‣ 主に散布図行列、統計モデル作成のために利用 ‣ RMongo はMongoDBから直接データを取り出せるドラ゗バ ‣ csvなどの中間フゔ゗ルが不要。バッチ処理向き ‣ まだα-バージョン ‣ Java Driverを直接使用する方法もある ‣ Red-Rで処理をフローで管理 ‣ Rの複雑な処理フローを可視化 ‣ 自動レポート機能:解析結果をpdf出力 ‣ 類似のツール:Rapid Miner 、Knime、R Analytic Flow
  46. 46. 解析ツール • ※以下の2ツールはデータのリッチな可視化が簡単にでき る • [tableau] ‣ 高性能統計解析ソフト(有料) ‣ Zyngaの解析チームが利用 ‣ データの様々な可視化が素早くできる • [bime] ‣ Web上の統計解析ソフト(無料プランは制限付き) ‣ AmazonS3、GoogleSpreadSheet、DBからもデータが取り込める ‣ 日本語は文字化けする
  47. 47. 解析ツール:bime
  48. 48. おみせやさんログ解析まとめ • [まとめ]:MongoDB の選択は間違ってなかった ‣ 500GB、10億レコードでもゆとりの性能 ‣ スキーマレスかつ検索クエリが豊富なのが強い ‣ データの増加に対しても容易にスケールできる ‣ 自前スクリプトも定義でき、コンソールから様々な操作がで きる ‣ 解析目的では、コレクション数や゗ンデックス対象になる項 目がそれほど多くない
  49. 49. MongoDB + Hadoop The Elephant In the Room: MongoDB + Hadoop [pdf]
  50. 50. これからやるべきこと • [解析] ‣ ゗ベント単位での解析。どの゗ベントがどのユーザー属性 性に効果があったのかを分析 ‣ ゕクセスログの活用。゗ベント告知など、意図したページ に確実に訪問してもらうため ‣ ゲーム内パラメータのチューニング ‣ リゕルタ゗ムに解析できる項目を増やしていく
  51. 51. 3. 応用的な解析事例紹介
  52. 52. お金持ちさん for mixi ▶ mixi 版リリース ▶ リリース直後から詳細な解析を行っている
  53. 53. 集計以外のログ解析 • [ゲーム内の状況把握]:リゕルタ゗ム解析 ‣ 何人がどのステージにいるのか ‣ 現在のユーザーのレベルや資産数、ゲーム内通貨の分布 ‣ 時間毎のUUや課金額の変化 ‣ 辞めたユーザーはどの段階で辞めたのか → これらの指標はリゕルタ゗ムで確認
  54. 54. 集計以外のログ解析 • [ゲームパラメータ調整]: ‣ ゕ゗テムの出現確率・価格の調整 ‣ 現在の難易度設定は適切か ‣ レゕゕ゗テムはレゕらしい振る舞いをしているか → 様々なデータに基づいてパラメータチューニング 非常にクリテゖカルで、 やりがいのある部分。 色々傾向がわかってきて、 今楽しい所。
  55. 55. GraphDBを利用した ソーシャルデータの解析
  56. 56. ソーシャルデータ解析 • ソーシャルデータはグラフ構造を持つ http://neo4j.org/doc/screenshots/
  57. 57. ソーシャルデータ解析 • グラフDBはノードとエッジ(リレーションシッ プ)とそれぞれの属性(プロパテゖ)で構成さ れる Graph Databases, NOSQL and Neo4j
  58. 58. ソーシャルデータ解析 • あらゆるデータはグラフ構造(例:Inseption) Neo4j for Ruby and Rails
  59. 59. ソーシャルデータ解析 • [RDB、MongoDBの限界]: ‣ node、edge のテーブルを作ってデータを格納するのは可能 RDBMongoDB
  60. 60. ソーシャルデータ解析 • [GraphDB]: ‣ データをグラフ構造のまま保存するのがGraphDB ‣ 全ての要素(ノード・エッジ)は接続しているものに直接ポ゗ ンター ‣ 企業も活用:Googleの Pregel、Twitterの FlockDB ‣ グラフ構造に特化した検索方法 > SELECT ?person WHERE { ?person KNOWS ?friend ?friend KNOWS ?classmate ?classname name “Takahiro Inoue” }
  61. 61. GraphDB:Neo4j • [Neo4j]:フリーの高機能 GraphDB ‣ Javaベース ‣ Ruby、Python、Groovyなどの数種のドラ゗バが存在 ‣ Luceneの゗ンデックスを利用して高速検索 ‣ 独自のQuery Languageを持つGremlinとの連携 ‣ 開発やユーザーグループが活発
  62. 62. GraphDB:Neo4j • [pythonでのサンプル]: //Create node: > n = graphdb.node() > n = graphdb.node(color="Red", widht=16, height=32) //Accessing node by id: > n17 = graphdb.node[14] // Accessing properties: > value = e['key'] # get property value > e['key'] = value # set property value > del e['key'] # remove property value // Create relationship: > n1.Knows(n2) //Specify properties for new relationships: > n1.Knows(n2, since=123456789, introduced_at="Christmas party”)
  63. 63. GraphDB:Neo4j • [pythonでのサンプル]: * Indexes //Get index: > index = graphdb.index("index name") //Create index: index = graphdb.index("some index", create=True) //Using indexes: > index['value'] = node > node = index['value'] > del index['value’]
  64. 64. GraphDB:Neo4j • [pythonでのサンプル]: class Friend(neo4j.Traversal): # Like queries in Neo4j types = [ neo4j.Outgoing.Knows ] order = neo4j.DEPTH_FIRST stop = neo4j.STOP_AT_END_OF_GRAPH returnable = neo4j.RETURN_ALL_BUT_START_NODE for friend_node in Friend(node1): print "%s (@ depth=%s)" % ( friend_node['name'], friend_node.depth ) for relationship in node1.Knows.outgoing: print relationship.getOtherNode(n1)
  65. 65. ソーシャルデータ解析 ※ 今後はソーシャルデータ解析にも注力 • [お金持ちさん事例]:ユーザー同士の資産の奪 い合い(ちょーだい)に関する解析 ‣ 1日ユーザーは何回ちょーだいをしたのか ‣ どの属性(レベル・課金額etc…)のユーザーにちょーだ いを何回して何回勝ったのか ‣ 高額課金者はどのような戦い方をしているのか ‣ etc… ユーザー同士の「交流」に関するデータを解析する
  66. 66. GraphDB:Neo4j • [お金持ちさんの”ちょーだい”解析]: ‣ 有向非連結単純グラフ(辺に向きがあってノードが複数のブロ ックに分かれていて多重辺やループの無いグラフ) ‣ 5万ノード、50万エッジ ‣ ノードはユーザー ‣ ノードの属性はユーザーの属性情報 ‣ ノード間のリレーション(エッジ)はあるユーザーが矢線の先 のユーザーにちょーだい(Commit)をしたことを意味する ‣ エッジの属性はそのユーザーに何回ちょーだい(total)をして 何回勝ったか(win)の頻度 今後はちょーだい対象と なった資産もノード・エ ッジに加えて行きたい。
  67. 67. GraphDB:Neo4j • [お金持ちさんの”ちょーだい”解析]:可視化
  68. 68. GraphDB:Neo4j • [お金持ちさんの”ちょーだい”解析]:可視化
  69. 69. GraphDB:Neo4j • [お金持ちさんの”ちょーだい”解析]:可視化 depth = 2
  70. 70. GraphDB:Neo4j • [お金持ちさんの”ちょーだい”解析]:可視化 depth = 3 depth を挙げていくと関連するノード・エッジの数は爆発的に増大する。 ノードやエッジに優先度の重みをつけてその重み付き確率に従ってサンプリングや探索を行う近似的ゕプローチ が重要になってくるはず。
  71. 71. Graph Programming Language:Gremlin • [Gremlin] ‣ GraphDBのクエリを簡単に扱うための Graph Programming Language ‣ 独自のコンソール上で操作が可能 ‣ Neo4jの他に数種類のGraphDBをサポート ‣ 実はMongoDBもサポート予定(今は?)
  72. 72. Graph Programming Language:Gremlin $./gremlin.sh ¥,,,/ (o o) -----oOOo-(_)-oOOo----- # neo4jのDBデータに接続 gremlin> $_g := neo4j:open('/data/Dropbox/Neo4j/daily/2010-11-11') ==>neo4jgraph[/data/Dropbox/Neo4j/daily/2010-11-11] # グラフのノードを全列挙 gremlin> $_g/V ==>v[0] ... ==>v[34269] # ノードの属性名の1つ、"name"の値で表示 gremlin> $_g/V/@name ==>いのうえたかひろ ==>doryokujin ...
  73. 73. Graph Programming Language:Gremlin # グラフのエッジを全列挙 gremlin> $_g/E ==>e[4][1-Commit->6] ==>e[3][1-Commit->5] ... # エッジの属性名の1つ、"total"の値で表示 gremlin> $_g/E/@total ==>1 ==>4 ... # エッジのリレーション名を表示 gremlin> $_g/E/@label Commit ... # エッジのリレーション名が"Commit"であるエッジのみを列挙 gremlin> $_g/E[@label="Commit"] ==>e[4][1-Commit->6] ==>e[3][1-Commit->5] ...
  74. 74. Graph Programming Language:Gremlin # 中心に据えるノードをid=5506に設定 gremlin> $_ := g:id-v(5506) ==>v[5506] # そのノードから発するエッジの数 gremlin> g:count(./bothE) ==>15 # そのノードに入るエッジの数 gremlin> g:count(./inE) ==>8 # そのノードから出るエッジの数 gremlin> g:count(./outE) ==>7 # そのノードから出るエッジの列挙 gremlin> ./outE ==>e[17142][5506-Commit->2672] ==>e[17141][5506-Commit->6275] ...
  75. 75. Graph Programming Language:Gremlin # v[5506]から出るエッジを受ける側のノード gremlin> ./outE[@label="Commit"]/inV ==>v[2672] ==>v[6275] ... # v[5506]から出るエッジを受ける側のノードの属性"name"の値 gremlin> ./outE[@label="Commit"]/inV/@name ==>いのうえたかひろ ==>doryokujin ... # v[5506]から出て他のノードに入ってそのノードから出るエッジの列挙 gremlin> ./outE[@label="Commit"]/inV/outE ==>e[35983][2672-Commit->10278] ==>e[35982][2672-Commit->12478] ...
  76. 76. Graph Programming Language:Gremlin # v[5506]から出て他のノードに入ってそのノードから出るエッジが入る側のノードの数 gremlin> g:count(./outE[@label="Commit"]/inV/outE[@label="Commit"]/inV) ==>12 gremlin> g:count(./bothE/bothV/outE/inV/outE) ==>504 # v[5506]の友達の友達の友達の数 gremlin> g:count(./bothE/bothV/bothE/bothV/bothE/bothV) ==>19102 # v[5506]の友達の友達の友達からでるエッジの数 gremlin> g:count(./bothE/bothV/bothE/bothV/bothE/bothV/bothE) ==>256369 # v[5506]の友達の友達の友達の友達の数 gremlin> g:count(./bothE/bothV/bothE/bothV/bothE/bothV/bothE/bothV) ==>512738 # v[5506]の友達の友達の友達の友達からでるエッジの数 gremlin> g:count(./bothE/bothV/bothE/bothV/bothE/bothV/bothE/bothV/bothE) ==>7667307
  77. 77. GraphDB:まとめ • [雑感] ‣ ソーシャルデータの解析にはGraphDBが有用 ‣ 特定の検索では他DBよりも優れたパフォーマンスを発揮 ‣ 今後GraphDBの重要性は高まってくると確信 ‣ 特にGoogleのGraphMapReduce可能なPregelは強力 ‣ 今まで計算困難だった情報が取得できる可能性 ‣ 確率的(乱択)ゕルゴリズムも重要になってくるはず ‣ Problem-Solving using Graph Traversals: Searching, Scoring, Ranking, and Recommendation は必読 ‣ graph-database.org には各種GraphDBの情報
  78. 78. 4. 最後に
  79. 79. 解析バックエンドとフロン トエンド ‣ 一言に解析と言ってもバックエンドとフロントエンドで全く異なる 仕事になる ‣ 散在するログの収集に始まり、いつでも解析できるような形式・場 所に格納するまでの基盤を構築するバックエンド ‣ ツールなどを駆使してデータを解析して人間の意志決定を支援する ための結果などを導くフロントエンド ‣ バックエンドはネットワークや゗ンフラ、DBの知識が必要。規模 や目的に合わせた設計が重要。とても泥臭い仕事 ‣ フロントエンドの解析者はいつでもデータが取り出せるという前提 のもと、バックを気にせず解析に専念できる事が望ましいのでは ‣ どちらも重要で必要だが、どちらの道で解析エキスパートになるか はちゃんと考えないといけないかも(僕はバックエンド側かな)
  80. 80. 最近感じていること ‣ データを出して社内で共有できるようになると、意外にたくさん の人が興味を持ってくれて、見て、仮説を立て、実証して、意志 決定に役立ててくれるようになった ‣ 「こういうデータが見たい」と要望がどんどん出るようになって とても嬉しい。さらに「データ見るの楽しい」とか言われるとエ ンジニゕ冥利に尽きます、幸せです ‣ それなりに高度で多様なデータ解析をやっているという自負があ る。そして今後それが結果につながると信じている ‣ しかしそれができるのも゗ンフラやゕプリ開発者がきちんとログ を扱いやすい形で出してくれたり、こちらの要望も聞いてくれる から。そのありがたみを忘れてはいけない
  81. 81. ありがとうございました ※次回はGraphDBのより詳細な解説と具体例 を発表したいと思っています…

×