前提
- 作業マシンにインストールして使ってみる
- 作業マシンはOS X El Capitan(バージョン10.11.4)
install
brewで簡単に入る
brew install neo4j
Javaが必要なので入ってなければ入れる
brew cask install java
起動
➜ ~ neo4j start
Unable to find any JVMs matching version "1.7".
Starting Neo4j Server...WARNING: not changing user
process [57371]... waiting for server to be ready............... OK.
http://localhost:7474/ is ready.
http://localhost:7474/
ブラウザで管理画面みたいなのにアクセスできる
最初にID,PW入力を求められるが最初はneo4j
,neo4j
でログインできる
neo4jのディレクトリ構成
/usr/local/Cellar/neo4j/2.3.2
├── bin ・・・起動系スクリプト
│ ├── neo4j -> ../libexec/bin/neo4j
│ ├── neo4j-import -> ../libexec/bin/neo4j-import
│ └── neo4j-shell -> ../libexec/bin/neo4j-shell
└── libexec
├── bin ・・・起動系スクリプト
│ ├── neo4j
│ ├── neo4j-import
│ ├── neo4j-installer
│ ├── neo4j-shell
│ └── utils
├── conf ・・・設定系ディレクトリ
│ ├── neo4j-http-logging.xml
│ ├── neo4j-server.properties
│ ├── neo4j-wrapper.conf
│ ├── neo4j.properties
│ └── ssl
│ ├── snakeoil.cert
│ └── snakeoil.key
├── data ・・・実データやlogが出力されるディレクトリ
│ ├── dbms
│ │ └── auth
│ ├── graph.db
│ │ └── store_lock
│ ├── log
│ │ └── console.log
│ └── neo4j-service.pid
├── lib ・・・coreライブラリ群
├── plugins ・・・プラグイン
│ └── README.txt
└── system ・・・neo4jのコア
まぁ各ディレクトリにREADMEあるので読めば詳しくわかります
試しのテストデータの準備
- 異なるジャンルのお店が2つあり、それぞれの商品を一般消費者が購入することをイメージ
- データ構造は下記
├── category1
│ └── shop1
│ ├── item1
│ └── item2
└── category2
└── shop2
└── item3
-
category1
という食品カテゴリにはshop1
があり、商品item1(9500円)
,item2(1200円)
がある -
category1
という雑貨カテゴリにはshop2
があり、商品item3(15000円)
がある
─── users
├── user1
├── user2
├── user3
└── user4
- 消費者が4人いる
-
user1
はitem1
を購入 -
user2
もitem1
を購入 -
user3
はitem2
を購入 -
user4
はitem3
を購入
上記のデータをCSVで用意
users.csv
user_id:ID,name,email,age:int,industry,gender,:LABEL
user1,user_name1,1@example.com,37,サービス業,male,user
user2,user_name2,2@example.com,17,ネットサービス,male,user
user3,user_name3,3@example.com,27,公務員,female,user
user4,user_name4,4@example.com,44,公務員,male,user
orders.csv
order_id:ID,user_id,shop_id,category_id,price,item_id,:LABEL
order1,user1,shop1,cate1,9500,item1,order
order2,user2,shop1,cate1,9500,item1,order
order3,user3,shop1,cate1,1200,item2,order
order4,user4,shop2,cate2,15000,item3,order
items.csv
tem_id:ID,name,shop_id,:LABEL
item1,商品A,shop1,item
item2,商品B,shop1,item
item3,商品C,shop2,item
shops.csv
shop_id:ID,name,category_id,:LABEL
shop1,ショップA,cate1,shop
shop2,ショップB,cate2,shop
category.csv
category_id:ID,name,:LABEL
cate1,カテゴリ1,category
cate2,カテゴリ2,category
データの投入
CSVからデータ投入は2種類ある
LOAD CSV
- 既存のDBに対してノードや関係性の追加や削除、属性の追加、削除、更新をする
- Javaのヒープメモリを気にする必要がある
LOAD CSV FROM 'file:///path/users.csv' AS line
CREATE (:user { email:line[1], gender:line[2], age:toInt(line[3]), industry:line[4] })
neo4j-importコマンド
- 新規のDBに対してノードや関係性の追加や削除、属性の追加、削除、更新をする
- Javaのヒープメモリを気にしなくて良い
- 今回はこっちを利用
➜ neo4j neo4j-import --into /usr/local/Cellar/neo4j/2.3.2/libexec/data/graph2.db --nodes category.csv --nodes items.csv --nodes orders.csv --nodes shops.csv --nodes users.csv
Unable to find any JVMs matching version "1.7".
Importing the contents of these files into /usr/local/Cellar/neo4j/2.3.2/libexec/data/graph2.db:
Nodes:
/Users/a12091/neo4j/category.csv
/Users/a12091/neo4j/items.csv
/Users/a12091/neo4j/orders.csv
/Users/a12091/neo4j/shops.csv
/Users/a12091/neo4j/users.csv
Available memory:
Free machine memory: 17.46 MB
Max heap memory : 1.78 GB
Nodes
[*>:??--------------------------------------------------------------------------------------|||] 10k
Done in 722ms
Prepare node index
[*DETECT:7.63 MB-------------------------------------------------------------------------------] 0
Done in 22ms
Calculate dense nodes
[*>:??-----------------------------------------------------------------------------------------] 0
Done in 10ms
Relationships
[*>:??-----------------------------------------------------------------------------------------] 0
Done in
Node --> Relationship
[*v:??-----------------------------------------------------------------------------------------] 10k
Done in 12ms
Relationship --> Relationship
[*>:??-----------------------------------------------------------------------------------------] 0
Done in 11ms
Node counts
[>|*COUNT:76.29 MB-----------------------------------------------------------------------------] 10k
Done in 76ms
Relationship counts
[*>:??-----------------------------------------------------------------------------------------] 0
Done in
IMPORT DONE in 2s 354ms. Imported:
15 nodes
0 relationships
67 properties
入った
続いてRelationships設定
- RelationshipsようのCSVを用意すれば、そのまま投入できるが、ここでは基本データはCSVでCypherからRelationships設定という流れにする
ユーザと購入を紐付け
MATCH (o:order),(u:user)
WHERE o.user_id = u.user_id
CREATE (u)-[:BUY]->(o);
購入データと商品を紐付け
MATCH (o:order),(i:item)
WHERE o.item_id = i.item_id
CREATE (o)-[:ORDER]->(i);
お店と商品を紐付け
MATCH (s:shop),(i:item)
WHERE s.shop_id = i.shop_id
CREATE (i)-[:PART]->(s);
お店とお店のジャンルを紐付け
MATCH (c:category),(s:shop)
WHERE c.category_id = s.category_id
CREATE (s)-[:CATE]->(c);
管理画面から見てみる
- 色の設定とかはしてあげると綺麗に見える
注意
- 管理画面からは参照先のDBの変更はできない様子
-
neo4j/2.3.2/libexec/conf/neo4j-server.properties
の参照DBを変えてる必要あり - 変更後は
neo4j restart
で
データを操作する - Cypher QL -
- CypherはNeo4jのグラフ構造のデータ処理を扱う際に使うSQLライクなQuery Language
実行ツール
Neo4jウェブインターフェース
Neo4j標準でついている。WEBから実行可能(http://localhost:7474/)
Neo4jシェル
neo4j-shellで起動してコンソールからCypherを流して使う
API経由
REST API
Neo4jドライバー
主要な各言語からアクセスして操作できる
基本(取得)
すべてのノードを取得
MATCH (n) RETURN n
すべてのノードとrelashonship取得
MATCH (n -[r]-> m) RETURN n,r,m;
削除
すべてのノードを削除
MATCH n DELETE n;
すべてのノードとrelashonshipを削除
MATCH (n -[r]-> m) DELETE n,r,m;
削除裏技(data配下をrm)
/usr/local/Cellar/neo4j/2.3.2/libexec/data
ここからNeo4j(Graph DB)を活用しているメリット
Graph Algorithms
下記のコンポーネントが含まれてる
- Shortest paths
- all paths
- all simple paths
- Dijkstra and
- A*
ひとつひとつをしっかり見ると深すぎるので、分かりやすいShortest paths
を例に扱って見る
Shortest paths = 最短経路
ex1
user_name1
とuser_name3
は今は友達ではないが、友達にさせるにはどんな共通項目があるかと調べる
コンソールから
neo4j-sh (?)$ MATCH p=shortestPath(
> (a:user {name:"user_name1"})-[*]-(b:user {name:"user_name3"})
> )
> RETURN p;
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| p |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| [Node[11]{user_id:"user1",name:"user_name1",email:"1@example.com",age:37,industry:"サービス業",gender:"male"},:BUY[0]{},Node[5]{order_id:"order1",user_id:"user1",shop_id:"shop1",category_id:"cate1",price:"9500",item_id:"item1"},:ORDER[4]{},Node[2]{item_id:"item1",name:"商品A",shop_id:"shop1"},:PART[8]{},Node[9]{shop_id:"shop1",name:"ショップA",category_id:"cate1"},:PART[9]{},Node[3]{item_id:"item2",name:"商品B",shop_id:"shop1"},:ORDER[6]{},Node[7]{order_id:"order3",user_id:"user3",shop_id:"shop1",category_id:"cate1",price:"1200",item_id:"item2"},:BUY[2]{},Node[13]{user_id:"user3",name:"user_name3",email:"3@example.com",age:27,industry:"公務員",gender:"female"}] |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row
18 ms
分かりにくいので管理画面から
- ショップAという店で商品を購入していることが共有項目となり、結び付けることができる
ex2
user_name1
とuser_name2
は今は友達ではないが、友達にさせるにはどんな共通項目があるかと調べる
管理画面から
- 今度は商品Aという同じものを購入していることが共有項目となり、かつより近いところでつながり、結び助けることができる
RDBだったら面倒なSQLがCypherなら超楽
ex1
ショップAで男性購入者に人気の商品は(購入回数の多いのは)何か?を抽出しようとした時
mysqlの場合
- RDBの設計によるが大まかこんな感じになる。tableをjoinしまくってselectする
- またはsqlとプログラムを組み合わせて抽出する
select *
from
購入Table
left join 商品Table
on 購入Table.item_id = 商品Table.id
left join ユーザTable
on 購入Table.user_id = ユーザTable.id
left join ショップTable
on 購入Table.shop_id = ショップTable.id
where
ユーザTable.gender = 'male'
AND
ショップTable.name = 'ショップA'
Cypherの場合
MATCH (u:user {gender: "male"})-->(o:order)-->(i:item)-->(s:shop)
WHERE s.name = "ショップA"
RETURN i.name
まとめ、使いどころ、雑感
- Graph Algorithmsを活用したSNS的なサービスの提供が可能(まぁみんなそう言ってる)
- 〇〇の友達がいいねと言っています。みたいなやつ
- 〇〇さんは友達ではないでしょうか?みたいなやつ
- Graph Algorithmsを活用したサービスの分析(CV分析)が可能
- 何かプロダクトがあり、様々なログをFluentあたりで収集して、Neo4jに突っ込む。
- プロダクトの会員データもどこかのタイミングでNeo4jに突っ込む
- あとはCypherをフル活用して分析してプロダクトへ反映する
- RDBだったら複雑なSQLで計算量も時間もかかっていたのが、何分の1かで実現できるので良い感じのリコメンド機能とか割と簡単にできそう
- どの商品にはどの属性のユーザが多く購入をする的なデータはすぐ計算・抽出する
- 抽出したデータをもとにレコメンドようのデータKVSに突っ込む
- ユーザの属性情報に基づいたレコメンドをKVSから取って表示してあげる
- まぁレコメンドはまたいろんなアルゴリズムが存在するし、一筋縄ではいかないよなぁ。。。
- Cypherをあまり詳しく記載しなかったが、http://neo4j.com/docs/stable/index.html を見ると面白そうなのがいっぱいある。Cypherの学習は面白そう
- データ分析ならぬデータ遊びで色々な傾向のデータが出せそうなきがする
- まぁ使いこなせればデータ分析系には強い武器になると思う
- ある程度つかんできたら、プロダクションのデータを一部持ってきて触った方が、よりリアリティがあるし、楽しくできると思う