100
94

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Pythonでグラフデータベース Neo4j入門 for ビギナー (Mac OSX向け)

Last updated at Posted at 2015-04-10

「Pythonでグラフデータベース Neo4j入門 for ビギナー」とか銘打っておきながら私自身もビギナーなので、すみません。
PythonでNeo4jを操作する環境構築と、データをいじってみるサンプルをご紹介します。

#1. Neo4jの導入#
まず、Mac OSXにNeo4Jを導入する方法から始めます。私の環境がYosemite 10.10.2なのでもし環境違いで何かエラー等あればコメント等で教えていただけると嬉しいです。

まず、JDKが必要ですが、Macに最初から入っているJavaではうまく動かないそうなので Oracle JDK 7を http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html から導入します。

次に、
http://neo4j.com/download/
にアクセスして、Neo4jのCommunity Edition(無料版)をダウンロードしてください。

neo4j-community-2.2.0-unix-2.tarがダウンロードされるので解凍してフォルダに入ります。

tar zvf neo4j-community-2.2.0-unix-2.tar
cd neo4j-community-2.2.0

そして起動します。

./bin/neo4j start

インストールは非常に簡単ですね!
ブラウザからアクセスできるユーザーインターフェースがあるので、それを使ってみていきます。
アクセス先は、
http://localhost:7474/browser/
です。
最初の起動時にIDとPasswordを設定することを求められるので、適宜設定します。

#2. PythonでNeo4jに接続する#
いくつかNeo4jに接続できるPythonライブラリがあるようですが、ここではNeo4jRestClientをつかってPythonからNeo4jに接続することにします。

pip install neo4jrestclient

pipって素晴らしいですね、インストールが本当に簡単! :laughing:

neo4jRestClientのチュートリアルに従って試していきます。

from neo4jrestclient.client import GraphDatabase

url = "http://<ユーザーID>:<パスワード>@localhost:7474/db/data/"
gdb = GraphDatabase(url)

<ユーザーID>と<パスワード>の部分には、先ほど設定したものを書いてください。
これでPythonからNeo4jに接続されます。

次にNodeを2つ足してみます。aliceとbobの同い年の2人です。

alice = gdb.nodes.create(name="Alice", age=30)
bob = gdb.nodes.create(name="Bob", age=30)

実はbobはaliceの事を1980年から知っていたのだけど、aliceがbobを知ったのは3年後だった・・・
というノードを追加すると下記になります。

bob.relationships.create("Knows", alice, since=1980)
alice.relationships.create("Knows", bob, since=1983)

ではこれを表示させて見ましょう。(iPython notebookでpython動かしている事を前提として進めます)

ノードとノードの関係を含めて全部表示させるクエリを叩きます。また、data_contents=Trueを設定することがキモで、これをつけないとうまく動きません。(これがわからずにちょっと時間を食いました・・・)

gdb.query("MATCH (n)-[r]-(m) RETURN n, r, m", data_contents=True)

neo4j_001-compressor.png
グラフが表示された!

これをブラウザ上で見てみるには、 http://localhost:7474/browser/ にアクセスして

MATCH (n)-[r]-(m) RETURN n, r, m

neo4j_002-compressor.png

を入力してEnterを押すと、
neo4j_003.png
グラフが表示されます :grinning:

#2. データをいじってみる#

先ほどまでのデータを一度削除します。

# All Delete
gdb.query("MATCH (n) OPTIONAL MATCH (n)-[r]-() DELETE n,r", data_contents=True)

その上で、3つのNode, Relationshipを追加します。

# Person Nodeの追加
alice = gdb.nodes.create(name="Alice", age=30)
bob   = gdb.nodes.create(name="Bob", age=30)
ken   = gdb.nodes.create(name="Ken", age=35)

alice.labels.add("Person")
bob.labels.add("Person")
ken.labels.add("Person")

# Relationshipの設定
bob.relationships.create("Knows", alice, since=1980)
alice.relationships.create("Knows", bob, since=1983)
alice.relationships.create("Knows", ken, since=2015)

Nodeというのはここでいうそれぞれの人のことを指し、RelationshipはAliceはBobを知っているといった関係性のことを指します。

neo4j_004-compressor-2.png

iPython上で表示のクエリを叩くと、

gdb.query("MATCH (n)-[r]-(m) RETURN n, r, m", data_contents=True)

neo4j_005-compressor.png

同じようなグラフが表示されます :D

次に書くPersonがBlogを持っていて、そのBlogとの関係性をブログの所持者:"Owner",購読者: "Subscribe"として定義してグラフを見てみます。

# Blog Nodeの追加
cam_blog  = gdb.nodes.create(name="Camera Blog")
comp_blog = gdb.nodes.create(name="Computer Blog")
trav_blog = gdb.nodes.create(name="Travel Blog")
gour_blog = gdb.nodes.create(name="Gourmet Blog")

cam_blog.labels.add("Blog")
comp_blog.labels.add("Blog")
trav_blog.labels.add("Blog")
gour_blog.labels.add("Blog")

# Relationの追加
alice.relationships.create("Own", cam_blog)
bob.relationships.create("Own", comp_blog)
ken.relationships.create("Own", trav_blog)

alice.relationships.create("Subscribe", trav_blog)
alice.relationships.create("Subscribe", gour_blog)
bob.relationships.create("Subscribe", cam_blog)
ken.relationships.create("Subscribe", comp_blog)

また、ブラウザで http://localhost:7474/browser/ にアクセスして下記のクエリを投げると、

MATCH (n)-[r]-(m) RETURN n, r, m

こんなグラフが表示されます。なかなか分かりやすいと思います。「グラフデータベースは関係性がリレーショナルデータベースよりもわかりやすい」、と言われるゆえんですねw
neo4j_006.png

#3. Cypherファーストステップ#

Cypherの基本的な書き方について例を幾つか挙げてみようと思います。


赤丸で示した下記のBob, Alice, Kenが選択されます。

match (n:Person) RETURN n

neo4j_007-compressor.png
(※ 赤枠は分かりやすさのために追加したものでNeo4Jのブラウザ画面でこの表示になるわけではありません)

今度はBlogのノードが選択されます。

match (n:Blog) RETURN n

neo4j_008-compressor.png

このCypherクエリはBobだけを抽出します。

MATCH (b:Person {name:'Bob'}) RETURN b

neo4j_009-compressor.png

関係も一緒に選択します。下記の場合はOwnの関係があるもののみが対象です。

MATCH (p:Person)-[r:Own]->(b:Blog) RETURN p,r,b;

neo4j_011-compressor.png

最後にランダムにPersonノードとBlogノードを100個ずつ生成して、そこに500のSubscribe関係を付与したグラフを生成して表示してみます。

import numpy.random as rd

l = 100

person_list = []
blog_list = []
for i in range(l):
    
    p = gdb.nodes.create(name="person_%d"%i)
    p.labels.add("Person")
    
    b  = gdb.nodes.create(name="Blog_%d"%i)
    b.labels.add("Blog")
    
    person_list.append(p)
    blog_list.append(b)

r1 = range(len(person_list))
rd.shuffle(r1)

for i in range(len(blog_list)):
    blog_list[i].relationships.create("Own", person_list[r1[i]])


r2 = range(l) * 5
rd.shuffle(r2)
r3 = range(l) * 5
rd.shuffle(r3)
                
for i,j in zip(r2, r3):
    person_list[i].relationships.create("Subscribe", blog_list[j])

neo4j_012-compressor.png

カオスですね! :grin:

#3.Networkxで描画#
iCypherをインストールします。

pip install ipython-cypher

下記のコードでnetworkxでグラフ化できます。

neo4j-networkx.py
%load_ext cypher
%matplotlib inline
import networkx as nx
import matplotlib.pyplot as plt

result = %%cypher http://ユーザーID:パスワード@localhost:7474/db/data/ MATCH (n)-[r]-(m) RETURN n,r,m;
node_map ={'Person':'#22FF99', 'Blog': '#6622FF' }
node_label={'Person':'Person', 'Blog': 'Blog' }

g = result.get_graph()
pos=nx.get_node_attributes(g,'pos')
plt.figure(figsize=(15,15))
nx.draw(g, node_color=[node_map[g.node[n]['labels'][0]] for n in g],node_size=80, width=0.5, edge_color='#999999')

neo4j_014-compressor.png

100
94
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
100
94

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?