[db tech showcase Tokyo 2015] E27: Neo4jグラフデータベース by クリエーションライン株式会社 李昌桓
Neo4jは、グラフ理論をデータベースエンジンの設計思想として採用しているDBMS (Data Base Management System)です。特にNeo4jが、他のグラフデータベースに比べ、一目をおいていることは、データ処理にCypherというSQLライクなクエリ言語が使えるということです。Cypherは、関係型データベースでさえ苦手とするとても複雑なジョインが絡む処理や、そもそもSQLではアルゴリズムの限界があるデータ処理にも対応できます。
Copyright ⓒ2015 CREATIONLINE,INC. All Rights Reserved
パターン
様々なグラフの形状
グラフは、どのような事象でも抽象化できる
20
A
A B
A’
Learning Neo4j、Rik Van Bruggen
在りのまま
22.
Copyright ⓒ2015 CREATIONLINE,INC. All Rights Reserved
データモデル(雛形)
21
ユーザー 販売履歴
注文した
• データモデル
ER図と似ていますが、正規化の観点からみると、データのドメイン(エンティティ)を認識する程度の緩いもの
であり、在りのまま…ドメイン間の関係性の認識を重視しています
:ラベル
:ラベル
:関係性
23.
Copyright ⓒ2015 CREATIONLINE,INC. All Rights Reserved
グラフ化
22• グラフ
• データ
CSV, JSON
uid U000001
born 1949
gender man
oid 20140905081933-U001343
number 5
price 9359
datetime 2014-09-05 08:19:33
date 2014-09-05
U000001
20140905
081933-
U001343
:注文した
• グラフ
最小単位は1ノード(丸1個)
24.
Copyright ⓒ2015 CREATIONLINE,INC. All Rights Reserved
関係型DBのデータ処理
23
顧客Aの名称、商品名、購入金額を出力する
基本的にインデックスを利用し、データ間の関係性を紐解きながらデータ処理を行う
25.
Copyright ⓒ2015 CREATIONLINE,INC. All Rights Reserved
SQL
24
SELECT 顧客.顧客名, 商品.商品名, 販売履歴.数量 *販売履歴.単価 AS 金額
FROM 顧客, 販売履歴, 商品
WHERE 顧客.顧客ID = 販売履歴.顧客ID
AND 顧客.顧客名="A"
AND 販売履歴.商品ID = 商品.商品ID
顧客.顧客名 商品.商品名 金額
A c ¥4,500
関係性をSQLの中に指定してもらう
データの大半は関係性を紐解くことである
26.
Copyright ⓒ2015 CREATIONLINE,INC. All Rights Reserved
グラフDBのデータ処理
25
顧客Aの名称、商品名、購入金額を計算する
関係性の永続化 関係性の永続化
関係性が永続化されている
永続化された関係性の上で、パターンマッ
チングを行う
とても複雑なSQL処理、SQLでは不可能な関
係性の処理に対応可能である
27.
Copyright ⓒ2015 CREATIONLINE,INC. All Rights Reserved
Cypher Query(Neo4j)
26
MATCH (顧客 {顧客名: "A"})-->(販売履歴)-->(商品)
RETRUN 顧客.顧客名, 商品.商品名, 販売履歴.数量 * 販売履歴.単価 AS 金額
顧客.顧客名 商品.商品名 金額
A b ¥4,500
既定の関係性を利用するので、関係性は記号(-->, <--, --)で表現する
関係性を紐解く必要がないため、その余力を強い関係性の処理に当てる
Copyright ⓒ2015 CREATIONLINE,INC. All Rights Reserved
Cyhper Query
• グラフ構造のデータ処理のために開発された宣言型Query言語
永続化された関係性の下で、とても短い構文で複雑なデータ処理を可能にする
• パタンマッチング
SQLのジョインを超える複雑な関係性の処理
• スキーマレス
アプリケーションデータベース
• シンプルなデータタイプ
文字列/小数/16進数8進数/整数/ブーリン型
• インデックス
一意性の保障、グラフの開始ノードの検索
• 実行計画
RULE BASE, COST BASE
44
46.
Copyright ⓒ2015 CREATIONLINE,INC. All Rights Reserved
Cyper Queryの構文
45
Cypher SQL
MATCH ...RETURN SELECT + JOIN
WHERE WHERE
WITH…パイプ WITH…テンプレート
CREATE CREATE
MERGE CREATE or UPDATE
DELETE DELETE
CREATR INDEX CREATR INDEX
EXPLAIN/PROFILE EXPLAIN PLAN
Cypherは、パターンマッチング(多次元的なジョインが可能)
現実世界のデータは、殆どが多次元的な構造
パターンマッチングの概念に慣れると…その後はSQLよりも遥かに簡単に書ける
47.
Copyright ⓒ2015 CREATIONLINE,INC. All Rights Reserved
データ作成・更新・削除
• 作成(CREATE)
CREATE (u:User { uid:“U00001”,born:1963})
• 更新(MATCH ...MERGE)
MATCH (u:User { uid:“U00001”)
MERGE SET u.born=1973
• 削除(MATCH ...DELETE)
MATCH (u:User { uid:“U00001”)
DELETE u
46
アプリケーション-->RESTful APIをラッピングし、データはJSONで
やり取りする。
48.
Copyright ⓒ2015 CREATIONLINE,INC. All Rights Reserved
BULK DATA(LOAD CSV)
• ソースデータはヘッダ付きのCSV
uid,born,gender
U000001,1949,man
U000002,1979,woman
…
• 登録(LOAD CSV…CREATE)
LOAD CSV WITH HEADERS FROM "file:///C:/Temp/data/user.csv" AS line
CREATE (u:User { uid:line.uid, born:toInt(line.born) })
・更新/削除
LOAD CSV...MATCH...MERGE...
LOAD CSV...MATCH...DELETE
47
49.
Copyright ⓒ2015 CREATIONLINE,INC. All Rights Reserved
関係性の作成
• MATCH...CREATE
48
U00001
20140905
222502-
U000724
PLACED
{関係性ID: ユーザノードID:販売履歴ノードID:方向}
MATCH
(user:User { uid:“U00001}),
(order:Order { oid:”20140905222502-U000724”)
CREATE
(user)-[:PLACED]->(order)
Copyright ⓒ2015 CREATIONLINE,INC. All Rights Reserved
デモ1:売上集計:グラフ表現
50
MATCH
(y:Year {year:2014})-->(m:Month {month:9})-->(d:Day
{day:5})-->(h:Hour {hour:22})-->(o)-[:CONTAINS]->(g)
RETURN *
販売履歴
商品
日付
月
日
年
52.
Copyright ⓒ2015 CREATIONLINE,INC. All Rights Reserved
デモ2:売上集計:データ表現
51
MATCH
(y:Year {year:2014})-->(m:Month {month:9})-->(d:Day {day:5})--
>(h:Hour {hour:22})-->(o)-[:CONTAINS]->(g)
RETURN g.gid AS 商品, o.number*o.price AS 価格 LIMIT 5
商品 価格
G0038 10,336
G0192 4,288
G0038 15,508
G0175 2,992
G0070 6,098
53.
Copyright ⓒ2015 CREATIONLINE,INC. All Rights Reserved
デモ3:レコメンデーション
52
//①売上トップ10のユーザーと金額
MATCH (y:Year {year:2014})-->(m:Month {month:9})-->(d)-->(h)-->(o)<-[:PLACED]-(u)
WITH u, sum(o.number * o.price) AS total
ORDER BY total DESC
LIMIT 10
//②売上トップ10のユーザーが購入した商品一覧
MATCH (u)-->(o)-[:CONTAINS]->(g), (y:Year {year:2014})-->(m:Month {month:9})-->(d)-->(h)-
->(o)
WITH distinct g
//③売上トップ10のユーザーが購入した商品のなかで売れ筋トップ10
MATCH (y:Year {year:2014})-->(m:Month {month:9})-->(d)-->(h)-->(o)-[:CONTAINS]->(g)
RETURN *
LIMIT 10
54.
Copyright ⓒ2015 CREATIONLINE,INC. All Rights Reserved
デモ4:レコメンデーション
53
//①売上トップ10ユーザー
MATCH (y:Year {year:2014})-->(m:Month {month:9})-->(d)-->(h)-->(o)<-[:PLACED]-(u)
WITH u, sum(o.number * o.price) AS total
ORDER BY total DESC
LIMIT 10
//②売上トップ10ユーザーが購入している商品
MATCH (u)-->(o)-[:CONTAINS]->(g), (y:Year {year:2014})-->(m:Month {month:9})-->(d)-->(h)-->(o)
WITH distinct g
//③売上トップ10ユーザーが購入している商品で売れ筋トップ10⇒ABC
MATCH (y:Year {year:2014})-->(m:Month {month:9})-->(d)-->(h)-->(o)-[:CONTAINS]->(g)
WITH g.gid AS ggid, sum( o.number * o.price) AS total
ORDER BY total DESC
LIMIT 10
//④ABCのどれらかを購入しているユーザーと商品一覧⇒abc
WITH collect(ggid) AS cggid UNWIND cggid AS gx
MATCH (u)-->(o)-[:CONTAINS]->(g:Goods { gid:gx}), (y:Year {year:2014})-->(m:Month {month:9})-->(d)-->(h)-->(o)
WITH cggid AS list1, u.uid AS uuid, collect(g.gid) AS list2
ORDER BY uuid
//LIMIT 10
//⑤ABCとabcを比較し、購入していないABCを薦める
RETURN uuid AS ユーザID, filter( x IN list1 WHERE NOT ( x IN list2)) AS 推薦商品一覧
LIMIT 10
55.
Copyright ⓒ2015 CREATIONLINE,INC. All Rights Reserved
デモ5:クロス集計
54
//①ユーザー毎の売上金額の計算し、CASE文で金額範囲毎のユーザー数にカウントする
MATCH (y:Year {year:2014})-->(m:Month {month:9})-->(d)-->(h)-->(o)<-[:PLACED]-(u)
WITH u.uid AS uuid, sum(o.number * o.price) AS total
WITH
CASE WHEN total <10000 THEN count(uuid) END AS lt10000,
CASE WHEN total >=10000 AND total <50000 THEN count(uuid) END AS lt50000,
CASE WHEN total >=50000 AND total <100000 THEN count(uuid) END AS lt100000,
CASE WHEN total >=100000 AND total <150000 THEN count(uuid) END AS lt150000,
CASE WHEN total >=150000 THEN count(uuid) END AS gt150000
//②①の結果をリストにまとめる
WITH collect(lt10000) AS lt10000,
collect(lt50000) AS lt50000,
collect(lt100000) AS lt100000,
collect(lt150000) AS lt150000,
collect(gt150000) AS gt150000
//③結果をリストから取り出す
RETURN
head(lt10000) AS 金額1万以下,
head(lt50000) AS 金額5万以下,
head(lt100000) AS 金額10万以下,
head(lt150000) AS 金額15万以下,
head(gt150000) AS 金額15万上
Copyright ⓒ2015 CREATIONLINE,INC. All Rights Reserved
デモ7:最短経路
56
MATCH
(startLeaf:Alphabet { name:"A" }),
(endLeaf:Alphabet { name:"Z" }),
valuePath= shortestPath((startLeaf)-[:NEXT*]->(endLeaf))
RETURN
extract( n IN nodes(valuePath) | n.name ) AS 経路,
length(valuePath) AS 区間数,
reduce(totalCost=0, n IN relationships(valuePath) | totalCost + n.charge)
AS 料金
経路 区間数 料金
[A, U, V, W, X, Y, Z] 6 60
58.
Copyright ⓒ2015 CREATIONLINE,INC. All Rights Reserved
デモ8:最多経路
57
MATCH
(startLeaf:Alphabet { name:"A" }),
(endLeaf:Alphabet { name:"Z" }),
valuePath=(startLeaf)-[:NEXT*]->(endLeaf)
RETURN
extract( n IN nodes(valuePath) | n.name ) AS 経路,
length(valuePath) AS 区間数,
reduce(totalCost=0, n IN relationships(valuePath) | totalCost + n.charge) AS
料金
経路 区間数 料金
[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z] 25 250
[A, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z] 22 220
[A, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z] 18 180
[A, B, C, D, E, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z] 22 220
[A, E, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z] 19 190
[A, O, P, Q, R, S, T, U, V, W, X, Y, Z] 12 120
[A, B, C, D, E, F, G, H, I, O, P, Q, R, S, T, U, V, W, X, Y, Z] 20 200
[A, E, F, G, H, I, O, P, Q, R, S, T, U, V, W, X, Y, Z] 17 170
[A, I, O, P, Q, R, S, T, U, V, W, X, Y, Z] 13 130
[A, B, C, D, E, I, O, P, Q, R, S, T, U, V, W, X, Y, Z] 17 170
[A, E, I, O, P, Q, R, S, T, U, V, W, X, Y, Z] 14 140
[A, U, V, W, X, Y, Z] 6 60
[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, U, V, W, X, Y, Z] 20 200
[A, E, F, G, H, I, J, K, L, M, N, O, U, V, W, X, Y, Z] 17 170
[A, I, J, K, L, M, N, O, U, V, W, X, Y, Z] 13 130
[A, B, C, D, E, I, J, K, L, M, N, O, U, V, W, X, Y, Z] 17 170
[A, E, I, J, K, L, M, N, O, U, V, W, X, Y, Z] 14 140
[A, O, U, V, W, X, Y, Z] 7 70
[A, B, C, D, E, F, G, H, I, O, U, V, W, X, Y, Z] 15 150
[A, E, F, G, H, I, O, U, V, W, X, Y, Z] 12 120
[A, I, O, U, V, W, X, Y, Z] 8 80
[A, B, C, D, E, I, O, U, V, W, X, Y, Z] 12 120
[A, E, I, O, U, V, W, X, Y, Z] 9 90
59.
Copyright ⓒ2015 CREATIONLINE,INC. All Rights Reserved
可視化の意義①
• グラフの正確さを検証する
グラフは、殆どが多次元表現であるために関係性が正しく作られているのかどうかは、サンプルを出力してみな
いと検証が困難である
58
Learning Neo4j、Rik Van Bruggen
60.
Copyright ⓒ2015 CREATIONLINE,INC. All Rights Reserved
可視化の意義②
• パターンマッチンがイメージできる
グラフのパターンから構文を検証しなら最終結果に辿りつく。特に複雑なパターンマッチングの構文作成では、
不可欠である。
59