はじめに
この記事は、AMBL株式会社 Advent Calendar 2022の15日目の記事になります。是非、他の記事も読んで見て下さい〜
最近、業務でグラフ型DBであるNeo4jを使う機会があったのですが、筆者はグラフDBを扱うのが初めてだった事もあり、色々と四苦八苦した部分もあり...
今回の記事は、シンプルにNeo4jにPythonを用いてデータ登録するまでの流れを簡単にメモ書きしていきます。
環境設定
今回実装していた筆者の環境は、macOS Big Sur (version 11.6)になります。
まずは必要なツールを、ターミナル上でインストールします。
とは言っても、特にこれといって面倒な作業はありません。
下記の homebrew
コマンドを叩けばOKです。
$ brew install neo4j
pythonは3.7以降のversionであれば、問題なく動きます。
今回使用するライブラリは以下の二つです。
$ pip3 install neo4j
$ pip3 install pandas
pythonからNeo4jを操作するために必要なdriverはneo4j
ライブラリ1個で完結しています。
めっちゃ便利ですね。
今回は登録するデータをCSV形式で持っている、という前提で進めていきますので、CSVを読み込むようにpandasを使用します。(楽なので)
Neo4j 起動
上記のコマンドが正常に完了したら、neo4jのサーバを起動します。
サーバ起動コマンド
$ neo4j start
サーバ終了コマンド
$ neo4j stop
サーバ状態確認コマンド
$ neo4j status
正常に起動すれば、下記のようなログが表示されます。
最後にThere may be a short delay until the server is ready.
と表示されていれば問題ないです。
ちなみに、default設定でneo4jのサーバを起動した際はローカルにNeo4jサーバが立ち上げられます。
その際の利用ポートの設定状態は、下記の通りです。
Port | 説明 |
---|---|
7687 | Neo4j本体 |
7474 | 管理コンソール(Neo4j Browser)のホスティング用 |
では、管理コンソール画面に移動してみます。
ブラウザ上でhttp://localhost:7474/
にアクセスしましょう。
Neo4j コンソール画面
http://localhost:7474/
にアクセスすると、初期状態ではこのような画面が表示されます。
ここでは、ログインIDとpasswordを求められます。
ログイン情報の初期設定値はこちらになります↓
ID | Password |
---|---|
neo4j | neo4j |
* ログイン後、passwordの変更求められます。ご対応ください。
ログインができれば、コンソール画面に正常に遷移します。
とは言っても、この段階では特にデータ登録などされていないので、空っぽのDBがあるだけです。
では、早速Pythonからデータ登録をしていきましょう。
Neo4jへのデータ登録
今回、登録するデータはこちら。
relation | from_node_type | from_node | to_node_type | to_node |
---|---|---|---|---|
父 | テレパシー | アーニャ・フォージャー | スパイ | ロイド・フォージャー |
母 | テレパシー | アーニャ・フォージャー | 暗殺者 | ヨル・フォージャー |
飼い犬 | テレパシー | アーニャ・フォージャー | 予知能力 | ボンド・フォージャー |
母の弟 | テレパシー | アーニャ・フォージャー | 特殊警察 | ユーリ・ブライアン |
もじゃもじゃ | テレパシー | アーニャ・フォージャー | 情報屋 | フランキー |
怖い人 | テレパシー | アーニャ・フォージャー | スパイ | フィオナ・フロスト |
妻 | スパイ | ロイド・フォージャー | 暗殺者 | ヨル・フォージャー |
夫 | 暗殺者 | ヨル・フォージャー | スパイ | ロイド・フォージャー |
pet | スパイ | ロイド・フォージャー | 予知能力 | ボンド・フォージャー |
pet | 暗殺者 | ヨル・フォージャー | 予知能力 | ボンド・フォージャー |
シスコン | 特殊警察 | ユーリ・ブライアン | 暗殺者 | ヨル・フォージャー |
恋慕 | スパイ | フィオナ・フロスト | スパイ | ロイド・フォージャー |
敵 | 特殊警察 | ユーリ・ブライアン | スパイ | ロイド・フォージャー |
恋敵 | スパイ | フィオナ・フロスト | 暗殺者 | ヨル・フォージャー |
仲間 | 情報屋 | フランキー | スパイ | ロイド・フォージャー |
必要あれば、上記の表をexcelにコピペして作成してみてください。
では、上記のデータをまとめたcsvファイルにtest.csv
とし、実際にDBに登録していきましょう。
まずは、ライブラリのインストール。
from neo4j import GraphDatabase, basic_auth
import pandas as pd
その後、Neo4jserverに接続・操作を行うdriverの設定。
# neo4j serverに接続するdriverの設定
driver = GraphDatabase.driver('neo4j://localhost:7687', auth=('neo4j', '****'))
ここまでできれば、接続準備は完了。
実際に、読み込むデータのロード。
demo_path = 'test.csv'
df = pd.read_csv(demo_path, encoding='sjis')
今回はNeo4jにデータを登録する手順として、
- まずnode情報の登録する
- 登録されたnodeにrelationを作成する
の順番に処理します。
実際に処理する関数をここでは先に定義しています。
-
nodeを登録するNeo4jのクエリコマンド
CREATE (f:{label}:character [name: $name]) RETURN f
-
relationを登録するNeo4jのクエリコマンド
MATCH (f1:character {name: $from_node})
MATCH (f2:character {name: $to_node})
f'CREATE (f1)-[:{relation}]->(f2)
ここでは、上記のコマンドでデータを登録しているんだな、くらいに思ってもらえればOKです。
def add_node(tx, pair_node_info):
for name, label in pair_node_info:
query = f'CREATE (f:{label}:character [name: $name]) RETURN f'
query = query.replace("[", "{").replace("]", "}")
tx.run(query, name=name)
def add_relation(tx, row):
from_node = row["from_node"]
to_node = row["to_node"]
relation = row["relation"]
tx.run('MATCH (f1:character {name: $from_node})'
'MATCH (f2:character {name: $to_node})'
f'CREATE (f1)-[:{relation}]->(f2)',
from_node=from_node, relation=relation, to_node=to_node)
では、早速node情報を登録していきましょう。
そのコマンドはこちら。
node_list = []
label_list = []
node_list += df["from_node"].to_list()
label_list += df["from_node_type"].to_list()
node_list += df["to_node"].to_list()
label_list += df["to_node_type"].to_list()
pair_node_info = []
for idx in range(len(node_list)):
pair_node_info.append((node_list[idx], label_list[idx]))
pair_node_info = list(set(pair_node_info))
with driver.session() as session:
session.write_transaction(add_node, pair_node_info)
次に、relation情報を登録していきましょう。
そのコマンドはこちら。
def apply_relation(row):
with driver.session() as session:
session.write_transaction(add_relation, row)
df.apply(apply_relation, axis=1)
これらを実行して登録は完了。
結構あっさりしていたかなと思います。
では、コンソール画面に戻って実際にみてみましょう。
画面のコマンド入力部分にMATCH (n) RETURN n LIMIT 25
と入力すると、
下記のような画面が表示されます。(見やすいように形だけ、整形しています。)
簡単な人物相関図ができました
とまぁ、こんな感じで簡単にデータの登録ができました。
ちょっと遊んでみる分にはいろいろ面白いですね。
最後に、登録した情報を全て削除したい場合は、下記を実行。
(コメントアウトしております。)
# def clear_db(tx):
# tx.run('MATCH (n) DETACH DELETE n')
# with driver.session() as session:
# session.write_transaction(clear_db)
終わりに
いかがでしたでしょうか?
グラフ型DBは使い所が難しい気もしますが、DBとして関係性を情報として検索できるのは結構面白いですよね。皆様も機会があれば触ってみてください。
最後に、今回使用したソースコードを貼っておきます。
from neo4j import GraphDatabase, basic_auth
import pandas as pd
def add_node(tx, pair_node_info):
for name, label in pair_node_info:
query = f'CREATE (f:{label}:character [name: $name]) RETURN f'
query = query.replace("[", "{").replace("]", "}")
tx.run(query, name=name)
def add_relation(tx, row):
from_node = row["from_node"]
to_node = row["to_node"]
relation = row["relation"]
tx.run('MATCH (f1:character {name: $from_node})'
'MATCH (f2:character {name: $to_node})'
f'CREATE (f1)-[:{relation}]->(f2)',
from_node=from_node, relation=relation, to_node=to_node)
def apply_relation(row):
with driver.session() as session:
session.write_transaction(add_relation, row)
def main():
driver = GraphDatabase.driver('neo4j://localhost:7687', auth=('neo4j', 'ambl-neo4j'))
demo_path = 'test.csv'
df = pd.read_csv(demo_path, encoding='sjis')
node_list = []
label_list = []
node_list += df["from_node"].to_list()
label_list += df["from_node_type"].to_list()
node_list += df["to_node"].to_list()
label_list += df["to_node_type"].to_list()
pair_node_info = []
for idx in range(len(node_list)):
pair_node_info.append((node_list[idx], label_list[idx]))
pair_node_info = list(set(pair_node_info))
with driver.session() as session:
session.write_transaction(add_node, pair_node_info)
df.apply(apply_relation, axis=1)
if __name__ == ('__main__'):
main()