Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Neo4j ハンズオン
アジェンダ
• はじめに
• グラフDBの概要とNeo4j
• データ要素 of Neo4j
• データ操作 of Neo4j
• CSVアップロード
• ソーシャル・グラフ
• その他の話題
2
はじめに
3
自己紹介
• 名前:宮崎俊郎
• TIS株式会社
生産革新本部 生産革新部 生産技術R&D室
• 最近のお仕事
• 社内フレームワークの開発
• Xenlonマイグレーターの開発
4
宣伝:
Xenlon~神龍 マイグレーションサービス
• 大規模レガシーシステムを短期間で安全確実に
アプリケーション移行を実現
5
COBOL Java変換ツール
• 構文解析
• 依存関係分析
Neo4jとの出会い
• Neo4j ≔ グラフデータベースの一つ
• Xenlonマイグレーターで活用しました
• 構文解析結果の格納
• 依存関係や呼び出し関係を保存・検索
• GOTO文の変換の調査
• while文+その中で行先へswi...
グラフDBの概要とNeo4j
10
グラフとは
• 「グラフ(英: Graph)とは、ノード(頂点)群とノード間の
連結関係を表すエッジ(枝)群で構成される抽象データ型、
and・orその実装である具象データ型である。」
(Wikipediaより)
11
ノード
ノード
エッジ
グラフデータベースとは
今回のハンズオンでは、以下とする
• 「ノード」と「エッジ」及びそれらに紐づく
"プロパティ"(KV値)を扱うデータベース
• Neo4jでは
「ノード」をNode、
「エッジ」をRelationshipと呼ぶ
12
N...
RDBでも"グラフ"を表現できるけど…
• 例えば"友人関係"のグラフをRDBのテーブルで表現
できる
• ある人の友人を検索するクエリも書ける
13
personId Name
1 長友
2 平
3 三瓶
personId friendId
...
RDBでも"グラフ"を表現できるけど…
• ある人の友人の友人を検索する場合は?
14
personId Name
1 長友
2 平
3 三瓶
personId friendId
1 2
2 3
2 4
グラフデータベースの場合
• ある人の友人の友人を検索する場合は?
15
personId Name
1 長友
2 平
3 三瓶
personId friendId
1 2
2 3
2 4
長友
平
三瓶
データ構造の相違による性能差
16
personId Name
1 長友
2 平
3 三瓶
personId friendId
1 2
2 3
2 4
長友
平
三瓶
RDBの場合、
隣接Nodeの情報を別テーブルに持つ
グラフDBは
隣接No...
データ量が増大した場合の性能差
17
personId Name
1 長友
2 平
3 三瓶
personId friendId
1 2
2 3
2 4
長友
平
三瓶
深さが増大した場合の性能差
• リレーショナルデータベースでの友達の検索と
Neo4jでの効率的な検索の比較
18
深さ RDBMS
実行時間(秒)
Neo4j
実行時間(秒)
返された
レコード件数
2 0.016 0.01 ~2,500
3...
ネイティブ・グラフデータベース
• ある起点から関連を辿る操作(検索)に威力を発揮
19
長友
平
三瓶
起点
グラフデータベースについて
さらに詳しく…
以下のスライドがおすすめです
• 「GraphDB徹底入門」〜構造や仕組み理解から使い
どころ・種々のGraphDBの比較まで幅広く〜
• https://www.slideshare.net/dor...
Neo4j - グラフデータベース
23
Neo4j - Customers
24
Neo4j - Graph Database Use Case
When Connected Data Matters Most
• Fraud Detection
• Graph-Based Search
• Network & IT Ope...
Neo4j GraphGists -
https://neo4j.com/graphgists/
26
Neo4j - Graph Database Features
• ACID for Integrity
• Flexible Schema
• High-Performance Query Execution
• Cypher Query L...
グラフデータベースとは
今回のハンズオンでは、以下とする
• 「ノード」と「エッジ」及びそれらに紐づく
"プロパティ"(KV値)を扱うデータベース
• Neo4jでは
「ノード」をNode、
「エッジ」をRelationshipと呼ぶ
28
N...
データ要素 of Neo4j
29
Neo4jが扱うデータの例
30
:Person
{name:"長友",
age:31 }
:Team
{name:"インテル",
country:"Italy" }
:Person
{name:"三瓶",
age:41,
job:"芸人" }
データ要素(1)- ノード
• Node ≔ データレコード
• Label ≔ Nodeを分類する
• プロパティ ≔ データレコード内の個別データ
31
Node
Node
データ要素(1)- ノード
• Node ≔ データレコード
• Label ≔ Nodeを分類する
• プロパティ ≔ データレコード内の個別データ
32
:Person
:Team
データ要素(1)- ノード
• Node ≔ データレコード
• Label ≔ Nodeを分類する
• プロパティ ≔ データレコード内の個別データ
33
:Person
{name:"長友",
age:31 }
:Team
{name:"イ...
データ要素(2)- プロパティ
• Node内の個別データ
• Key-Value値
• 同じラベルのNodeでも異なるKeyセットを持てる
34
:Person
{name:"長友",
age:31 }
:Team
{name:"インテル",...
データ要素(3)-
リレーションシップ
• Relationship ≔ Node間の関係を示す
• Type ≔ Relationshipを分類する
• プロパティ ≔ Relationshipへも付与できる
35
Relationship
...
データ要素(3)-
リレーションシップ
• Relationship ≔ Node間の関係を示す
• Type ≔ Relationshipを分類する
• プロパティ ≔ Relationshipへも付与できる
36
:MARRIED
:KNO...
データ要素(3)-
リレーションシップ
• Relationship ≔ Node間の関係を示す
• Type ≔ Relationshipを分類する
• プロパティ ≔ Relationshipへも付与できる
37
:MARRIED
{at:...
データ要素 - まとめ
• Node ≔ データレコード
• Label ≔ Nodeを分類する
• プロパティ ≔ データレコード内の個別データ
• Relationship ≔ Node間の関係を示す
• Type ≔ Relationsh...
データ操作 of Neo4j
39
データ操作
• NodeとRelationshipのCRUD操作
40
Nodeの
・作成
・プロパティの追加/更新/削除
・削除 Relationshipの
・作成(結合)
・プロパティの追加/更新/削除
・削除(切断)
検索
Cypher = クエリ言語
• Neo4j独自のデータ操作DSL
• "Being a declarative language, Cypher focuses on the
clarity of expressing what to ret...
データ要素の表現
• Node
• Relationship
42
(:Person {name:"長友", age:31})
[:MEMBER_OF {since:2011}]
データ要素の表現
• Node
• Relationship
43
(:Person {name:"長友", age:31})
[:MEMBER_OF {since:2011}]
データ要素の表現
• Node
• Relationship
44
(:Person {name:"長友", age:31})
ラベル名
[:MEMBER_OF {since:2011}]
タイプ名
• アッパーキャメルケースによる記述が多い
...
データ要素の表現
• Node
• Relationship
45
(:Person {name:"長友", age:31})
プロパティ
[:MEMBER_OF {since:2011}]
プロパティ
• JSON形式に準じた記法
データ要素の表現 - まとめ
• Node…()で括る
• Relationship…[]で括る
46
(:Person {name:"長友", age:31})
ラベル名 プロパティ
[:MEMBER_OF {since:2011}]
タイプ...
パスの表現
• パス…( )-[ ]-( )
• パスの例
47
(:Person {name:"長友"})<-[:MARRIED]-(:Person {name:"平"})
プロパティ
ステートメント - CREATE
• CREATE…Nodeを作成
• 以下のクエリを実行して下さい
48
CREATE (:Person {name:"長友", age:31})
CREATE (:Person {name:"長友", age...
Neo4j Browser(1)
• 今回のハンズオンでは、Cypherクエリの実行に
「Neo4j Browser」を使います。
• Neo4j Browserの起動手順
• Neo4jコンソールアプリケーション(Neo4jサーバ)
を起動す...
Neo4j Browser(2)
• Neo4j Browserの使い方は、以下を参照してください
• GitHubの zackys/handson-neo4j の下の
doc/10_hands-on.md
• https://github.c...
ステートメント - CREATE
• CREATE…Nodeを作成
• 以下のクエリを実行して下さい
51
CREATE (:Person {name:"長友", age:31})
CREATE (:Person {name:"長友", age...
ステートメント -
MATCHとRETURN
• MATCH…パターンを指定して検索
• RETURN…検索結果を返す
52
MATCH (n) RETURN n
MATCH (n:Person) RETURN n
MATCH (n:Perso...
ステートメント - WHERE
• WHERE…検索条件を指定する(MATCHの後)
53
MATCH (n:Person)
WHERE n.age = 32
RETURN n.name AS name, n.age AS age
6
MATC...
ステートメント - CREATE(2)
• CREATE…Relationshipを作成
• NodeとRelationshipをまとめて作成
• 既存のNode間にRelationshipを作成
54
CREATE (:Person {nam...
ステートメント - CREATE(2)
• CREATE…Relationshipを作成
• NodeとRelationshipをまとめて作成
• 既存のNode間にRelationshipを作成
55
CREATE (:Person {nam...
ステートメント - CREATE(3)
• 前ページの と合わせて以下のクエリを実行
56
MATCH (nagatomo:Person {name:"長友"}),
(taira:Person {name:"平"}),
(sanpei:Pers...
ステートメント - SET
• SET…プロパティの追加・更新
• 追加
• 更新
57
MATCH (n:Person {name:"香川"})
SET n.from = "兵庫"
MATCH (n:Person {name:"香川"})
S...
ステートメント - REMOVE
• REMOVE…プロパティの削除
58
MATCH (n:Person {name:"香川"})
REMOVE n.from
13
ステートメント - DELETE
• DELETE…NodeやRelationshipの削除
• Relationshipの削除
• Nodeの削除
59
MATCH (n:Team {name:"ドルトムント"})
DELETE n
MATC...
DELETE時の注意事項
• NodeをDELETEする場合、そのNodeにつながる
Relationshipは事前に削除しておく必要がある
• または、DETACH DELETEを使う
• DETACH DELETEは、NodeにRelati...
パスをCypherで表現する(1)
【例】
61
()-[]->()
()<-[]-()
()-[]->()<-[]-()
パスをCypherで表現する(1)
【例】
62
()-[]->()
()<-[]-()
()-[]->()<-[]-()
パスをCypherで表現する(1)
【例】
63
()-[]->()
()<-[]-()
()-[]->()<-[]-()
(:Person {name:"長友"})<-[:MARRIED]-(:Person {name:"平"})
・・・「長...
パスをCypherで表現する(1)
【例】
64
()-[]->()
()<-[]-()
()-[]->()<-[]-()
パスをCypherで表現する(1)
【例】
65
()-[]->()
()<-[]-()
()-[]->()<-[]-()
・・・「長友が所属するチームに所属する本田」
=「長友のチームメイトの本田」
(:Person {name:"長友"})...
パスをCypherで表現する(2)
• パスの長さを指定
• 長さ0のパス=Nodeのみマッチ
• 向きの指定は省略可能
66
()-[:KNOWS*2]->()
()-[:KNOWS*1..3]->()
()-[*]->()
()-[:KNO...
パスをCypherで表現する(3)
• ループの表現(有向)
• ループの表現(無向)
67
(s)-[:GOTO*1..]->(s)
(s)-[:KNOWS*1..]-(s)
X
W
Y
Z
x
w
y
z
パスをCypherで表現する(4)
• xさんと同じ本とCDを買ったyさんを探す
68
MATCH (x)-[:BOUGHT]->(:Book)<-[:BOUGHT]-(y)
-[:BOUGHT]->(:CD)<-[:BOUGHT]-(x)
R...
パスをCypherで表現する(5)
• xさんと同じ本を買ったyさんにCDをおすすめする
69
MATCH (x)-[:BOUGHT]->(:Book)<-[:BOUGHT]-(y)
-[:BOUGHT]->(n:CD)<-[:BOUGHT]-...
パスを使って検索する(1)
• ⇒ MATCH句にパスを指定して検索する
• 「長友の配偶者は?」
70
MATCH (:Person {name:"長友"})-[:MARRIED]-(n)
RETURN n.name
18
パスを使って検索する(2)
• ⇒ MATCH句にパスを指定して検索する
• 「長友のチームメイトは?」
• 「長友の日本代表のチームメイトは?」
71
MATCH (:Person {name:"長友"})-[:MEMBER_OF]->
(:...
CSVアップロード
72
CSVアップロード
• 用途
• RDB上のデータをインポート
• 外部データの取り込み
• など
• 今回は、後の「ソーシャル・グラフ」で使用する
データをアップロードしてみる
73
ステートメント - LOAD CSV
• LOAD CSV…CSVファイルのデータをNeo4jのワーク
メモリ上に読み込む
• ヘッダなし
• ヘッダあり
74
LOAD CSV FROM "https://file.csv"
LOAD CSV...
CSVファイル(ヘッダなし)
• 【例】Person.csv
75
LOAD CSV FROM "https://Person.csv"
長友,31
平,32
三瓶,41
本田,32
CSVファイル(ヘッダあり)
• 【例】Person.csv
76
LOAD CSV WITH HEADERS FROM "https://Person.csv"
name,age
長友,31
平,32
三瓶,41
本田,32
ヘッダ
ファイルについて
• ローカルディスク上のファイルでもOK
• ただし、$NEO4J_HOME/importディレクトリ直下に置く
• URIは、そこからの相対パス
• デリミタの指定も可能
77
LOAD CSV FROM "file:///...
ロードしたデータは
Cypherクエリで操作可能(1)
• パイプライン的に操作できる
78
LOAD CSV WITH HEADERS FROM "https://Person.csv"
AS line
RETURN line
LOAD CS...
ロードしたデータは
Cypherクエリで操作可能(2)
• パイプライン的に操作できる
79
LOAD CSV WITH HEADERS FROM "https://Person.csv"
AS line
MATCH (n:Person {na...
グラフデータの
アップロード戦略(1)
• 各NodeにはユニークなNodeIDを付与した上で
CSVファイル化する
• Person.csv
• Team.csv
80
id,name,age
1,長友,31
2,平,32
3,三瓶,41
4...
グラフデータの
アップロード戦略(2)
• Relationshipは、NodeIDをもとにした関係テーブル
としてCSVファイルを作成する
• MARRIED.csv
• MEMBER_OF.csv
81
from,to
2,1
person...
実際のアップロード(1)
• まず、すべてのNodeをアップロード
82
LOAD CSV WITH HEADERS FROM "https://Person.csv"
AS line
CREATE (:Person {personId:lin...
実際のアップロード(2)
• その後、Node間を結ぶRelationshipを生成
83
LOAD CSV WITH HEADERS FROM "https://MEMBER_OF.csv"
AS line
MATCH (x:Person {...
LOAD CSV を試す
• GitHub上のPerson.csvの内容を確認する
• https://github.com/zackys/handson-neo4j/blob/master/import/social/Person.csv
•...
次章で使うデータのアップロード
• データを全削除(MATCH (n) DETACH DELETE n)してから実行
85
LOAD CSV WITH HEADERS FROM "https://raw.githubusercontent.co...
ソーシャル・グラフ
86
サンプル・データの説明
• from O'reilly "Graph Databases"(邦訳:『グラフデータベース』)
87
サンプル・データの説明
• from O'reilly "Graph Databases"(邦訳:『グラフデータベース』)
88
:Person
サンプル・データの説明
• from O'reilly "Graph Databases"(邦訳:『グラフデータベース』)
89
:Company
:WORKS_FOR
サンプル・データの説明
• from O'reilly "Graph Databases"(邦訳:『グラフデータベース』)
90
:Project
:WORKED_ON
サンプル・データの説明
• from O'reilly "Graph Databases"(邦訳:『グラフデータベース』)
91
:Interest
:INTERESTED_IN
Warm Up
① 「Benの年齢は?」
② 「Benの関心事は?」
③ 「Benと同じプロジェクトで働く人は?」
92
:Interest
:Project
Warm Up - 解答例
① 「Benの年齢は?」
② 「Benの関心事は?」
③ 「Benと同じプロジェクトで働く人は?」
93
MATCH (n:Person {name:"Ben"}) RETURN n.name, n.age
MATC...
人気のある"関心事"は?
⇒
としても、登録済みのすべての関心事が返るだけ
94
MATCH (n:Interest) RETURN n.name
人気のある"関心事"は?
⇒考え方:
① パス を検索する
② "関心事"ごとにパス数を集計する
③ パス数の多い関心事
= 人気の関心事
95
(関心事)<-[:INTERESTED_IN]-(:Person)
①パスの検索
• パス を検索する
• 今回は、パスの代わりに両端ノードを返す
96
(関心事)<-[:INTERESTED_IN]-(:Person)
MATCH p=(i:Interest)<--(n:Person) RETURN p
MA...
集約関数 - COLLECT
• COLLECT…検索結果について集約し、
集約結果を1つの配列にして返す
97
MATCH (i:Interest)<--(n:Person)
RETURN i.name, n.name
MATCH (i:In...
集約関数 - COUNT
• COUNT…検索結果について集約し、
要素数を返す
98
MATCH (i:Interest)<--(n:Person)
RETURN i.name, COLLECT(n.name), COUNT(n.name)
...
②"関心事"ごとにパス数を集計
• COUNTを使い、趣味ごとにパス数を集計
99
MATCH (i:Interest)<--(n:Person)
RETURN i.name, n.name
MATCH (i:Interest)<--(n:Pe...
ORDER BY 句
• ORDER BY…検索結果をソートする
100
MATCH (i:Interest)<--(n:Person)
RETURN i.name, COUNT(i.name)
MATCH (i:Interest)<--(n:...
LIMIT 句
• LIMIT…検索結果数を制限する
101
MATCH (i:Interest)<--(n:Person)
RETURN i.name AS intr, COUNT(i.name) AS rank
ORDER BY rank ...
WITH 句を使い、クエリを整理
• WITH…中間結果を次のクエリへパイプする
102
MATCH (i:Interest)<--(n:Person)
RETURN i.name AS intr, COUNT(i.name) AS rank
...
共通の関心事を持つ同僚は?
① "Ben"と共通の関心事を持つ同僚は?
② その中で、より多く共通の関心事を持つ同僚は?
(①の結果を、共通の関心事の数でランク付ける)
103
共通の関心事を持つ同僚は?
① "Ben"と共通の関心事を持つ同僚は?
② その中で、より多く共通の関心事を持つ同僚は?
(①の結果を、共通の関心事の数でランク付ける)
104
MATCH (n:Person {name:"Ben"})
WIT...
共通の関心事を持つ同僚は?
- 解答例
① "Ben"と共通の関心事を持つ同僚は?
② その中で、より多く共通の関心事を持つ同僚は?
(①の結果を、共通の関心事の数でランク付ける)
105
MATCH (n:Person {name:"Ben"...
その他の話題
106
アプリケーションによる
Neo4jのデータ操作
• 以下の言語向けにAPIが提供されている
• C#
• Java
• JavaScript
• Python
• REST APIも提供
107
Javaアプリケーション
• OGM(= Object-Graph Mapping) Libraryが利用可能
• like ORMapper(Object-Relational Mapper)
• OGMを使ったサンプルアプリケーション
• ...
サンプル・アプリケーション
• メールユーザの送信記録を行う
109
ログ
Neo4j
ドメインモデルと
グラフデータの対応
JavaBeans(POJO) ⇔ Node
JavaBeans間の参照 ⇔ Relationship
110
dpt
BELONG_TO
▼
from
to
1
1..* ◀ SENT TO
◀ SENT...
113
ありがとうございました
Upcoming SlideShare
Loading in …5
×

Neo4j ハンズオン

466 views

Published on

Hands On for Neo4j Beginners

See https://github.com/zackys/handson-neo4j

Published in: Data & Analytics
  • Be the first to comment

  • Be the first to like this

Neo4j ハンズオン

  1. 1. Neo4j ハンズオン
  2. 2. アジェンダ • はじめに • グラフDBの概要とNeo4j • データ要素 of Neo4j • データ操作 of Neo4j • CSVアップロード • ソーシャル・グラフ • その他の話題 2
  3. 3. はじめに 3
  4. 4. 自己紹介 • 名前:宮崎俊郎 • TIS株式会社 生産革新本部 生産革新部 生産技術R&D室 • 最近のお仕事 • 社内フレームワークの開発 • Xenlonマイグレーターの開発 4
  5. 5. 宣伝: Xenlon~神龍 マイグレーションサービス • 大規模レガシーシステムを短期間で安全確実に アプリケーション移行を実現 5 COBOL Java変換ツール • 構文解析 • 依存関係分析
  6. 6. Neo4jとの出会い • Neo4j ≔ グラフデータベースの一つ • Xenlonマイグレーターで活用しました • 構文解析結果の格納 • 依存関係や呼び出し関係を保存・検索 • GOTO文の変換の調査 • while文+その中で行先へswitchするよう変換するのが常套 • でないと、ループ構造の場合にスタックオーバーフローの恐れ • ⇒ 呼び出し関係のうち、ループになるものを見つけ その一群を1つのwhile文へ変換 6
  7. 7. グラフDBの概要とNeo4j 10
  8. 8. グラフとは • 「グラフ(英: Graph)とは、ノード(頂点)群とノード間の 連結関係を表すエッジ(枝)群で構成される抽象データ型、 and・orその実装である具象データ型である。」 (Wikipediaより) 11 ノード ノード エッジ
  9. 9. グラフデータベースとは 今回のハンズオンでは、以下とする • 「ノード」と「エッジ」及びそれらに紐づく "プロパティ"(KV値)を扱うデータベース • Neo4jでは 「ノード」をNode、 「エッジ」をRelationshipと呼ぶ 12 Node Node Relationship
  10. 10. RDBでも"グラフ"を表現できるけど… • 例えば"友人関係"のグラフをRDBのテーブルで表現 できる • ある人の友人を検索するクエリも書ける 13 personId Name 1 長友 2 平 3 三瓶 personId friendId 1 2 2 3 2 4
  11. 11. RDBでも"グラフ"を表現できるけど… • ある人の友人の友人を検索する場合は? 14 personId Name 1 長友 2 平 3 三瓶 personId friendId 1 2 2 3 2 4
  12. 12. グラフデータベースの場合 • ある人の友人の友人を検索する場合は? 15 personId Name 1 長友 2 平 3 三瓶 personId friendId 1 2 2 3 2 4 長友 平 三瓶
  13. 13. データ構造の相違による性能差 16 personId Name 1 長友 2 平 3 三瓶 personId friendId 1 2 2 3 2 4 長友 平 三瓶 RDBの場合、 隣接Nodeの情報を別テーブルに持つ グラフDBは 隣接Nodeの情報を直接持つ
  14. 14. データ量が増大した場合の性能差 17 personId Name 1 長友 2 平 3 三瓶 personId friendId 1 2 2 3 2 4 長友 平 三瓶
  15. 15. 深さが増大した場合の性能差 • リレーショナルデータベースでの友達の検索と Neo4jでの効率的な検索の比較 18 深さ RDBMS 実行時間(秒) Neo4j 実行時間(秒) 返された レコード件数 2 0.016 0.01 ~2,500 3 30.267 0.168 ~110,000 4 1543.505 1.359 ~600,000 5 未完了 2.132 ~800,000 『Neo4j In Action』https://www.manning.com/books/neo4j-in-action
  16. 16. ネイティブ・グラフデータベース • ある起点から関連を辿る操作(検索)に威力を発揮 19 長友 平 三瓶 起点
  17. 17. グラフデータベースについて さらに詳しく… 以下のスライドがおすすめです • 「GraphDB徹底入門」〜構造や仕組み理解から使い どころ・種々のGraphDBの比較まで幅広く〜 • https://www.slideshare.net/doryokujin/graphdbgraphdb 20
  18. 18. Neo4j - グラフデータベース 23
  19. 19. Neo4j - Customers 24
  20. 20. Neo4j - Graph Database Use Case When Connected Data Matters Most • Fraud Detection • Graph-Based Search • Network & IT Operations • Real-Time Recommendation Engines • Master Data Management • Social Network • Identity & Access Management 25
  21. 21. Neo4j GraphGists - https://neo4j.com/graphgists/ 26
  22. 22. Neo4j - Graph Database Features • ACID for Integrity • Flexible Schema • High-Performance Query Execution • Cypher Query Language • Scale and Performance • Built-in Tooling & Visualization • Advanced Causal Clustering • Elastic Scalability • In-Memory Page Cache • Hot Backups 27 Community版で利用可能 Enterprise版で利用可能
  23. 23. グラフデータベースとは 今回のハンズオンでは、以下とする • 「ノード」と「エッジ」及びそれらに紐づく "プロパティ"(KV値)を扱うデータベース • Neo4jでは 「ノード」をNode、 「エッジ」をRelationshipと呼ぶ 28 Node Node Relationship
  24. 24. データ要素 of Neo4j 29
  25. 25. Neo4jが扱うデータの例 30 :Person {name:"長友", age:31 } :Team {name:"インテル", country:"Italy" } :Person {name:"三瓶", age:41, job:"芸人" }
  26. 26. データ要素(1)- ノード • Node ≔ データレコード • Label ≔ Nodeを分類する • プロパティ ≔ データレコード内の個別データ 31 Node Node
  27. 27. データ要素(1)- ノード • Node ≔ データレコード • Label ≔ Nodeを分類する • プロパティ ≔ データレコード内の個別データ 32 :Person :Team
  28. 28. データ要素(1)- ノード • Node ≔ データレコード • Label ≔ Nodeを分類する • プロパティ ≔ データレコード内の個別データ 33 :Person {name:"長友", age:31 } :Team {name:"インテル", country:Italy } :Person {name:"三瓶", age:41, job:"芸人" }
  29. 29. データ要素(2)- プロパティ • Node内の個別データ • Key-Value値 • 同じラベルのNodeでも異なるKeyセットを持てる 34 :Person {name:"長友", age:31 } :Team {name:"インテル", country:Italy } :Person {name:"三瓶", age:41, job:"芸人" }
  30. 30. データ要素(3)- リレーションシップ • Relationship ≔ Node間の関係を示す • Type ≔ Relationshipを分類する • プロパティ ≔ Relationshipへも付与できる 35 Relationship Relationship Relationship
  31. 31. データ要素(3)- リレーションシップ • Relationship ≔ Node間の関係を示す • Type ≔ Relationshipを分類する • プロパティ ≔ Relationshipへも付与できる 36 :MARRIED :KNOWS :MEMBER_OF
  32. 32. データ要素(3)- リレーションシップ • Relationship ≔ Node間の関係を示す • Type ≔ Relationshipを分類する • プロパティ ≔ Relationshipへも付与できる 37 :MARRIED {at:2017} :KNOWS :MEMBER_OF {since:2011} :MEMBER_OF {at:[2010,2014]}
  33. 33. データ要素 - まとめ • Node ≔ データレコード • Label ≔ Nodeを分類する • プロパティ ≔ データレコード内の個別データ • Relationship ≔ Node間の関係を示す • Type ≔ Relationshipを分類する • プロパティ ≔ Relationshipへも付与できる 38
  34. 34. データ操作 of Neo4j 39
  35. 35. データ操作 • NodeとRelationshipのCRUD操作 40 Nodeの ・作成 ・プロパティの追加/更新/削除 ・削除 Relationshipの ・作成(結合) ・プロパティの追加/更新/削除 ・削除(切断) 検索
  36. 36. Cypher = クエリ言語 • Neo4j独自のデータ操作DSL • "Being a declarative language, Cypher focuses on the clarity of expressing what to retrieve from a graph, not on how to retrieve it." 41 どのように検索するのかではなく、 何を検索するかにフォーカスする =
  37. 37. データ要素の表現 • Node • Relationship 42 (:Person {name:"長友", age:31}) [:MEMBER_OF {since:2011}]
  38. 38. データ要素の表現 • Node • Relationship 43 (:Person {name:"長友", age:31}) [:MEMBER_OF {since:2011}]
  39. 39. データ要素の表現 • Node • Relationship 44 (:Person {name:"長友", age:31}) ラベル名 [:MEMBER_OF {since:2011}] タイプ名 • アッパーキャメルケースによる記述が多い • Case Sensitive • スネークケースによる記述が多い • Case Sensitive
  40. 40. データ要素の表現 • Node • Relationship 45 (:Person {name:"長友", age:31}) プロパティ [:MEMBER_OF {since:2011}] プロパティ • JSON形式に準じた記法
  41. 41. データ要素の表現 - まとめ • Node…()で括る • Relationship…[]で括る 46 (:Person {name:"長友", age:31}) ラベル名 プロパティ [:MEMBER_OF {since:2011}] タイプ名 プロパティ
  42. 42. パスの表現 • パス…( )-[ ]-( ) • パスの例 47 (:Person {name:"長友"})<-[:MARRIED]-(:Person {name:"平"}) プロパティ
  43. 43. ステートメント - CREATE • CREATE…Nodeを作成 • 以下のクエリを実行して下さい 48 CREATE (:Person {name:"長友", age:31}) CREATE (:Person {name:"長友", age:31}) CREATE (:Person {name:"平", age:32}) CREATE (:Person {name:"本田", age:31}) CREATE (:Person {name:"三瓶", age:41, job:"芸人"}) CREATE (:Person {name:"ガリアルディーニ", age:23}) CREATE (:Team {name:"インテル"}) CREATE (:Team {name:"日本代表"}) 1
  44. 44. Neo4j Browser(1) • 今回のハンズオンでは、Cypherクエリの実行に 「Neo4j Browser」を使います。 • Neo4j Browserの起動手順 • Neo4jコンソールアプリケーション(Neo4jサーバ) を起動する • http://localhost:7474へアクセス • 認証画面が表示された場合は以下を入力 • user ⇒ neo4j • password ⇒ Neo4jインストール時に設定したパスワード 49
  45. 45. Neo4j Browser(2) • Neo4j Browserの使い方は、以下を参照してください • GitHubの zackys/handson-neo4j の下の doc/10_hands-on.md • https://github.com/zackys/handson-neo4j/blob/master/doc/10_hands-on.md • 「Neo4j Browser(2)」に手順に従って操作して 見て下さい • ハンズオンで入力するCypherクエリは、 このページからコピーして下さい。 50
  46. 46. ステートメント - CREATE • CREATE…Nodeを作成 • 以下のクエリを実行して下さい 51 CREATE (:Person {name:"長友", age:31}) CREATE (:Person {name:"長友", age:31}) CREATE (:Person {name:"平", age:32}) CREATE (:Person {name:"本田", age:31}) CREATE (:Person {name:"三瓶", age:41, job:"芸人"}) CREATE (:Person {name:"ガリアルディーニ", age:23}) CREATE (:Team {name:"インテル"}) CREATE (:Team {name:"日本代表"}) 1 クエリ実行後、お気に入りへ登録した「MATCH (n) RETURN n」を実行し、 Nodeの登録を確認する
  47. 47. ステートメント - MATCHとRETURN • MATCH…パターンを指定して検索 • RETURN…検索結果を返す 52 MATCH (n) RETURN n MATCH (n:Person) RETURN n MATCH (n:Person) RETURN n.name, n.age, n.job MATCH (n:Person {age:32}) RETURN n.name AS name 2 3 4 5 プロパティ値指定 戻り値に名前をつける
  48. 48. ステートメント - WHERE • WHERE…検索条件を指定する(MATCHの後) 53 MATCH (n:Person) WHERE n.age = 32 RETURN n.name AS name, n.age AS age 6 MATCH (n:Person) WHERE n.age > 40 RETURN n.name AS name, n.age AS age 7
  49. 49. ステートメント - CREATE(2) • CREATE…Relationshipを作成 • NodeとRelationshipをまとめて作成 • 既存のNode間にRelationshipを作成 54 CREATE (:Person {name:"香川", age:28}) -[:MEMBER_OF]-> (:Team {name:"ドルトムント"}) MATCH (x:Person {name:"長友"}), (y:Person {name:"平"}) CREATE (y)-[:MARRIED {at:2017}]->(x) MATCHの結果を利用する 8 9
  50. 50. ステートメント - CREATE(2) • CREATE…Relationshipを作成 • NodeとRelationshipをまとめて作成 • 既存のNode間にRelationshipを作成 55 CREATE (:Person {name:"香川", age:28}) -[:MEMBER_OF]-> (:Team {name:"ドルトムント"}) MATCH (x:Person {name:"長友"}), (y:Person {name:"平"}) CREATE (y)-[:MARRIED {at:2017}]->(x) MATCHの結果を利用する 8 9
  51. 51. ステートメント - CREATE(3) • 前ページの と合わせて以下のクエリを実行 56 MATCH (nagatomo:Person {name:"長友"}), (taira:Person {name:"平"}), (sanpei:Person {name:"三瓶"}), (honda:Person {name:"本田"}), (kagawa:Person {name:"香川"}), (gagl:Person {name:"ガリアルディーニ"}), (japan:Team {name:"日本代表"}), (intel:Team {name:"インテル"}) CREATE (taira)-[:KNOWS]->(sanpei) CREATE (nagatomo)-[:MEMBER_OF {since:2011}]->(intel) CREATE (nagatomo)-[:MEMBER_OF {at:[2010,2014]}]->(japan) CREATE (honda)-[:MEMBER_OF {at:[2010,2014]}]->(japan) CREATE (kagawa)-[:MEMBER_OF {at:[2014]}]->(japan) CREATE (gagl)-[:MEMBER_OF {since:2017}]->(intel) 10 8 9 クエリ実行後、お気に入りへ登録した「MATCH (n) RETURN n」を実行し、 Relationshipの作成を確認する
  52. 52. ステートメント - SET • SET…プロパティの追加・更新 • 追加 • 更新 57 MATCH (n:Person {name:"香川"}) SET n.from = "兵庫" MATCH (n:Person {name:"香川"}) SET n.from = "神戸" 11 12
  53. 53. ステートメント - REMOVE • REMOVE…プロパティの削除 58 MATCH (n:Person {name:"香川"}) REMOVE n.from 13
  54. 54. ステートメント - DELETE • DELETE…NodeやRelationshipの削除 • Relationshipの削除 • Nodeの削除 59 MATCH (n:Team {name:"ドルトムント"}) DELETE n MATCH (x:Person {name:"香川"})-[r]-> (y:Team {name:"ドルトムント"}) DELETE r 14 15 MATCHしたRelationshipに 名前をつけておく
  55. 55. DELETE時の注意事項 • NodeをDELETEする場合、そのNodeにつながる Relationshipは事前に削除しておく必要がある • または、DETACH DELETEを使う • DETACH DELETEは、NodeにRelationshipが残っていても、 Relationshipを含め削除してくれる 60 MATCH (n:Person {name:"香川"}) DELETE n 16 MATCH (n:Person {name:"香川"}) DETACH DELETE n 17 エラー! まだ(日本代表)に属して いるので、削除できない
  56. 56. パスをCypherで表現する(1) 【例】 61 ()-[]->() ()<-[]-() ()-[]->()<-[]-()
  57. 57. パスをCypherで表現する(1) 【例】 62 ()-[]->() ()<-[]-() ()-[]->()<-[]-()
  58. 58. パスをCypherで表現する(1) 【例】 63 ()-[]->() ()<-[]-() ()-[]->()<-[]-() (:Person {name:"長友"})<-[:MARRIED]-(:Person {name:"平"}) ・・・「長友と結婚した平愛梨」
  59. 59. パスをCypherで表現する(1) 【例】 64 ()-[]->() ()<-[]-() ()-[]->()<-[]-()
  60. 60. パスをCypherで表現する(1) 【例】 65 ()-[]->() ()<-[]-() ()-[]->()<-[]-() ・・・「長友が所属するチームに所属する本田」 =「長友のチームメイトの本田」 (:Person {name:"長友"})-[:MEMBER_OF]->(:Team) <-[:MEMBER_OF]-(:Person {name="本田"})
  61. 61. パスをCypherで表現する(2) • パスの長さを指定 • 長さ0のパス=Nodeのみマッチ • 向きの指定は省略可能 66 ()-[:KNOWS*2]->() ()-[:KNOWS*1..3]->() ()-[*]->() ()-[:KNOWS*0..3]->() ()-[:KNOWS]-()
  62. 62. パスをCypherで表現する(3) • ループの表現(有向) • ループの表現(無向) 67 (s)-[:GOTO*1..]->(s) (s)-[:KNOWS*1..]-(s) X W Y Z x w y z
  63. 63. パスをCypherで表現する(4) • xさんと同じ本とCDを買ったyさんを探す 68 MATCH (x)-[:BOUGHT]->(:Book)<-[:BOUGHT]-(y) -[:BOUGHT]->(:CD)<-[:BOUGHT]-(x) RETURN y MATCH (x)-[:BOUGHT]->(:Book)<-[:BOUGHT]-(y), (x)-[:BOUGHT]->(:CD)<-[:BOUGHT]-(y) RETURN y x :Book :CD y or 検索対象 :BOUGHT :BOUGHT :BOUGHT :BOUGHT
  64. 64. パスをCypherで表現する(5) • xさんと同じ本を買ったyさんにCDをおすすめする 69 MATCH (x)-[:BOUGHT]->(:Book)<-[:BOUGHT]-(y) -[:BOUGHT]->(n:CD)<-[:BOUGHT]-(x) RETURN n MATCH (x)-[:BOUGHT]->(:Book)<-[:BOUGHT]-(y), (x)-[:BOUGHT]->(n:CD)<-[:BOUGHT]-(y) RETURN n x :Book :CD y or :BOUGHT :BOUGHT :BOUGHT :BOUGHT検索対象
  65. 65. パスを使って検索する(1) • ⇒ MATCH句にパスを指定して検索する • 「長友の配偶者は?」 70 MATCH (:Person {name:"長友"})-[:MARRIED]-(n) RETURN n.name 18
  66. 66. パスを使って検索する(2) • ⇒ MATCH句にパスを指定して検索する • 「長友のチームメイトは?」 • 「長友の日本代表のチームメイトは?」 71 MATCH (:Person {name:"長友"})-[:MEMBER_OF]-> (:Team)<-[:MEMBER_OF]-(n) RETURN n.name MATCH (:Person {name:"長友"})-[:MEMBER_OF]-> (:Team {name:"日本代表"})<-[:MEMBER_OF]-(n) RETURN n.name 19 20
  67. 67. CSVアップロード 72
  68. 68. CSVアップロード • 用途 • RDB上のデータをインポート • 外部データの取り込み • など • 今回は、後の「ソーシャル・グラフ」で使用する データをアップロードしてみる 73
  69. 69. ステートメント - LOAD CSV • LOAD CSV…CSVファイルのデータをNeo4jのワーク メモリ上に読み込む • ヘッダなし • ヘッダあり 74 LOAD CSV FROM "https://file.csv" LOAD CSV WITH HEADERS FROM "https://file.csv" CSVファイル CSVファイル
  70. 70. CSVファイル(ヘッダなし) • 【例】Person.csv 75 LOAD CSV FROM "https://Person.csv" 長友,31 平,32 三瓶,41 本田,32
  71. 71. CSVファイル(ヘッダあり) • 【例】Person.csv 76 LOAD CSV WITH HEADERS FROM "https://Person.csv" name,age 長友,31 平,32 三瓶,41 本田,32 ヘッダ
  72. 72. ファイルについて • ローカルディスク上のファイルでもOK • ただし、$NEO4J_HOME/importディレクトリ直下に置く • URIは、そこからの相対パス • デリミタの指定も可能 77 LOAD CSV FROM "file:///social/Person.csv" $NEO4J_HOME/import/social/Person.csv LOAD CSV FROM "file:///social/Person.csv" FIELDTERMINATOR "t" タブ区切りの場合
  73. 73. ロードしたデータは Cypherクエリで操作可能(1) • パイプライン的に操作できる 78 LOAD CSV WITH HEADERS FROM "https://Person.csv" AS line RETURN line LOAD CSV WITH HEADERS FROM "https://Person.csv" AS line RETURN line.id, line.name ヘッダ付きでLOADした場合、データ名で参照できる (JSONデータを参照している) 1行単位で、JSON形式で返す(ヘッダありの場合)
  74. 74. ロードしたデータは Cypherクエリで操作可能(2) • パイプライン的に操作できる 79 LOAD CSV WITH HEADERS FROM "https://Person.csv" AS line MATCH (n:Person {name:line.name}) RETURN n.age LOAD CSV WITH HEADERS FROM "https://Person.csv" AS line CREATE (:Person {name:line.name, age:line.age})
  75. 75. グラフデータの アップロード戦略(1) • 各NodeにはユニークなNodeIDを付与した上で CSVファイル化する • Person.csv • Team.csv 80 id,name,age 1,長友,31 2,平,32 3,三瓶,41 4,本田,32 RDBのテーブルデータのイメージ id,name,age 101,日本代表 102,インテル
  76. 76. グラフデータの アップロード戦略(2) • Relationshipは、NodeIDをもとにした関係テーブル としてCSVファイルを作成する • MARRIED.csv • MEMBER_OF.csv 81 from,to 2,1 personId,teamId 1,101 1,102 4,102 RDBの関係テーブルデータのイメージ
  77. 77. 実際のアップロード(1) • まず、すべてのNodeをアップロード 82 LOAD CSV WITH HEADERS FROM "https://Person.csv" AS line CREATE (:Person {personId:line.id, name:line.name}) LOAD CSV WITH HEADERS FROM "https://Team.csv" AS line CREATE (:Team {teamId:line.id, name:line.name})
  78. 78. 実際のアップロード(2) • その後、Node間を結ぶRelationshipを生成 83 LOAD CSV WITH HEADERS FROM "https://MEMBER_OF.csv" AS line MATCH (x:Person {personId:line.personId}), (y:Team {teamId:line.teamId}) CREATE (x)-[:MEMBER_OF]->(y)
  79. 79. LOAD CSV を試す • GitHub上のPerson.csvの内容を確認する • https://github.com/zackys/handson-neo4j/blob/master/import/social/Person.csv • ヘッダ付きCSVファイルのLOADと、列要素へのアクセス • 【参考】ヘッダなしCSVファイルとして読み込んだ場合 84 LOAD CSV WITH HEADERS FROM "https://raw.githubusercontent.com/zackys/handson-neo4j/master/import/social/Person.csv" AS line RETURN line 21 LOAD CSV WITH HEADERS FROM "https://raw.githubusercontent.com/zackys/handson-neo4j/master/import/social/Person.csv" AS line RETURN line.id, line.name, line.age LOAD CSV FROM "https://raw.githubusercontent.com/zackys/handson-neo4j/master/import/social/Person.csv" AS line RETURN line[0], line[1], line[2] LOAD CSV FROM "https://raw.githubusercontent.com/zackys/handson-neo4j/master/import/social/Person.csv" AS line RETURN line 22 23
  80. 80. 次章で使うデータのアップロード • データを全削除(MATCH (n) DETACH DELETE n)してから実行 85 LOAD CSV WITH HEADERS FROM "https://raw.githubusercontent.com/zackys/handson-neo4j/master/import/social/Person.csv" AS line CREATE (:Person {personId:line.id, name:line.name, age:line.age}) UNION LOAD CSV WITH HEADERS FROM "https://raw.githubusercontent.com/zackys/handson-neo4j/master/import/social/Company.csv" AS line CREATE (:Company {companyId:line.id, name:line.name}) UNION LOAD CSV WITH HEADERS FROM "https://raw.githubusercontent.com/zackys/handson-neo4j/master/import/social/Project.csv" AS line CREATE (:Project {projectId:line.id, name:line.name}) UNION LOAD CSV WITH HEADERS FROM "https://raw.githubusercontent.com/zackys/handson-neo4j/master/import/social/Interest.csv" AS line CREATE (:Interest {interestId:line.id, name:line.name}) LOAD CSV WITH HEADERS FROM "https://raw.githubusercontent.com/zackys/handson-neo4j/master/import/social/WORKS_FOR.csv" AS line MATCH (n1:Person {personId:line.personId}), (n2:Company {companyId:line.companyId}) CREATE (n1)-[:WORKS_FOR]->(n2) UNION LOAD CSV WITH HEADERS FROM "https://raw.githubusercontent.com/zackys/handson-neo4j/master/import/social/WORKED_ON.csv" AS line MATCH (n1:Person {personId:line.personId}), (n2:Project {projectId:line.projectId}) CREATE (n1)-[:WORKED_ON]->(n2) UNION LOAD CSV WITH HEADERS FROM "https://raw.githubusercontent.com/zackys/handson-neo4j/master/import/social/INTERESTED_IN.csv" AS line MATCH (n1:Person {personId:line.personId}), (n2:Interest {interestId:line.interestId}) CREATE (n1)-[:INTERESTED_IN]->(n2) 24 25
  81. 81. ソーシャル・グラフ 86
  82. 82. サンプル・データの説明 • from O'reilly "Graph Databases"(邦訳:『グラフデータベース』) 87
  83. 83. サンプル・データの説明 • from O'reilly "Graph Databases"(邦訳:『グラフデータベース』) 88 :Person
  84. 84. サンプル・データの説明 • from O'reilly "Graph Databases"(邦訳:『グラフデータベース』) 89 :Company :WORKS_FOR
  85. 85. サンプル・データの説明 • from O'reilly "Graph Databases"(邦訳:『グラフデータベース』) 90 :Project :WORKED_ON
  86. 86. サンプル・データの説明 • from O'reilly "Graph Databases"(邦訳:『グラフデータベース』) 91 :Interest :INTERESTED_IN
  87. 87. Warm Up ① 「Benの年齢は?」 ② 「Benの関心事は?」 ③ 「Benと同じプロジェクトで働く人は?」 92 :Interest :Project
  88. 88. Warm Up - 解答例 ① 「Benの年齢は?」 ② 「Benの関心事は?」 ③ 「Benと同じプロジェクトで働く人は?」 93 MATCH (n:Person {name:"Ben"}) RETURN n.name, n.age MATCH (:Person {name:"Ben"})-[:INTERESTED_IN]->(i) RETURN i.name MATCH (:Person {name:"Ben"})-[:WORKED_ON]->() <-[:WORKED_ON]-(coworker:Person) RETURN coworker.name
  89. 89. 人気のある"関心事"は? ⇒ としても、登録済みのすべての関心事が返るだけ 94 MATCH (n:Interest) RETURN n.name
  90. 90. 人気のある"関心事"は? ⇒考え方: ① パス を検索する ② "関心事"ごとにパス数を集計する ③ パス数の多い関心事 = 人気の関心事 95 (関心事)<-[:INTERESTED_IN]-(:Person)
  91. 91. ①パスの検索 • パス を検索する • 今回は、パスの代わりに両端ノードを返す 96 (関心事)<-[:INTERESTED_IN]-(:Person) MATCH p=(i:Interest)<--(n:Person) RETURN p MATCH (i:Interest)<--(n:Person) RETURN i.name, n.name 1 0
  92. 92. 集約関数 - COLLECT • COLLECT…検索結果について集約し、 集約結果を1つの配列にして返す 97 MATCH (i:Interest)<--(n:Person) RETURN i.name, n.name MATCH (i:Interest)<--(n:Person) RETURN i.name, n.name, COLLECT(n.name) MATCH (i:Interest)<--(n:Person) RETURN i.name, COLLECT(n.name) 1 2 3 i.nameとn.nameでgroup byされ、 各部分集合に対してCOLLECTが 実行される i.nameでgroup byされ、 各部分集合に対してCOLLECTが 実行される 全パスが返る
  93. 93. 集約関数 - COUNT • COUNT…検索結果について集約し、 要素数を返す 98 MATCH (i:Interest)<--(n:Person) RETURN i.name, COLLECT(n.name), COUNT(n.name) MATCH (i:Interest)<--(n:Person) RETURN i.name, COLLECT(n.name), COUNT(i.name) MATCH (i:Interest)<--(n:Person) RETURN i.name, COLLECT(n.name) 3 4 5 COUNT()の場合はnとiを入れ替えても結果は変わらない(後々のためiにする)
  94. 94. ②"関心事"ごとにパス数を集計 • COUNTを使い、趣味ごとにパス数を集計 99 MATCH (i:Interest)<--(n:Person) RETURN i.name, n.name MATCH (i:Interest)<--(n:Person) RETURN i.name, COUNT(i.name) 1 6
  95. 95. ORDER BY 句 • ORDER BY…検索結果をソートする 100 MATCH (i:Interest)<--(n:Person) RETURN i.name, COUNT(i.name) MATCH (i:Interest)<--(n:Person) RETURN i.name, COUNT(i.name) ORDER BY COUNT(i.name) DESC MATCH (i:Interest)<--(n:Person) RETURN i.name AS intr, COUNT(i.name) AS rank ORDER BY rank DESC 6 7 8
  96. 96. LIMIT 句 • LIMIT…検索結果数を制限する 101 MATCH (i:Interest)<--(n:Person) RETURN i.name AS intr, COUNT(i.name) AS rank ORDER BY rank DESC LIMIT 3 9 MATCH (i:Interest)<--(n:Person) RETURN i.name AS intr, COUNT(i.name) AS rank ORDER BY rank DESC 8
  97. 97. WITH 句を使い、クエリを整理 • WITH…中間結果を次のクエリへパイプする 102 MATCH (i:Interest)<--(n:Person) RETURN i.name AS intr, COUNT(i.name) AS rank ORDER BY rank DESC LIMIT 3 MATCH (i:Interest)<--(n:Person) WITH i.name AS intr RETURN intr, COUNT(intr) AS rank ORDER BY rank DESC LIMIT 3 9 10
  98. 98. 共通の関心事を持つ同僚は? ① "Ben"と共通の関心事を持つ同僚は? ② その中で、より多く共通の関心事を持つ同僚は? (①の結果を、共通の関心事の数でランク付ける) 103
  99. 99. 共通の関心事を持つ同僚は? ① "Ben"と共通の関心事を持つ同僚は? ② その中で、より多く共通の関心事を持つ同僚は? (①の結果を、共通の関心事の数でランク付ける) 104 MATCH (n:Person {name:"Ben"}) WITH n MATCH (n) MATCH (n:Person {name:"Ben"}) WITH n MATCH (n)
  100. 100. 共通の関心事を持つ同僚は? - 解答例 ① "Ben"と共通の関心事を持つ同僚は? ② その中で、より多く共通の関心事を持つ同僚は? (①の結果を、共通の関心事の数でランク付ける) 105 MATCH (n:Person {name:"Ben"}) WITH n MATCH (n)-[:INTERESTED_IN]->()<-[:INTERESTED_IN]-(x), (n)-[:WORKED_ON]->()<-[:WORKED_ON]-(x) RETURN x MATCH (n:Person {name:"Ben"}) WITH n MATCH (n)-[:INTERESTED_IN]->(i)<-[:INTERESTED_IN]-(x), (n)-[:WORKED_ON]->(p)<-[:WORKED_ON]-(x) WITH i.name AS intr, x.name AS name RETURN name, COUNT(intr) AS rank, COLLECT(intr)
  101. 101. その他の話題 106
  102. 102. アプリケーションによる Neo4jのデータ操作 • 以下の言語向けにAPIが提供されている • C# • Java • JavaScript • Python • REST APIも提供 107
  103. 103. Javaアプリケーション • OGM(= Object-Graph Mapping) Libraryが利用可能 • like ORMapper(Object-Relational Mapper) • OGMを使ったサンプルアプリケーション • https://github.com/zackys/handson-neo4j/tree/master/sample02 108
  104. 104. サンプル・アプリケーション • メールユーザの送信記録を行う 109 ログ Neo4j
  105. 105. ドメインモデルと グラフデータの対応 JavaBeans(POJO) ⇔ Node JavaBeans間の参照 ⇔ Relationship 110 dpt BELONG_TO ▼ from to 1 1..* ◀ SENT TO ◀ SENT BY User userId name address Email mailId title Dpt name
  106. 106. 113 ありがとうございました

×