🥑
Graph DBを触ってみた: ArangoDB, Neo4j, Dgraphの比較
この記事では、Neo4j、ArangoDB、Dgraphの3つのGraph DBをDockerでサクッと動かし、Pythonからもサクッと動かしてみます。
各DBの特徴
Neo4j
古参Graph DB。Cypherでクエリを記述する。最近は生成AI向けに頑張ってる模様。
GraphDBのクエリ言語を見れば大体当てはまるが、CypherであればGraphデータを以下のように直感的に表現できる。
MATCH (p:Product)-[:CATEGORY]->(l:ProductCategory)-[:PARENT*0..]
->(:ProductCategory {name:"Dairy Products"})
RETURN p.name
SQLだとこんな感じ。一目瞭然ですね。
SELECT p.ProductName
FROM Product AS p
JOIN ProductCategory pc ON (p.CategoryID = pc.CategoryID
AND pc.CategoryName = "Dairy Products")
JOIN ProductCategory pc1 ON (p.CategoryID = pc1.CategoryID)
JOIN ProductCategory pc2 ON (pc1.ParentID = pc2.CategoryID
AND pc2.CategoryName = "Dairy Products")
JOIN ProductCategory pc3 ON (p.CategoryID = pc3.CategoryID)
JOIN ProductCategory pc4 ON (pc3.ParentID = pc4.CategoryID)
JOIN ProductCategory pc5 ON (pc4.ParentID = pc5.CategoryID
AND pc5.CategoryName = "Dairy Products");
Pulseを見るとそこまで開発はアクティブではない。
ArangoDB
AQL(ArangoDB Query Language)を用いる。構造化データ、半構造化データ、および非構造化データを、スキーマフリーの JSON オブジェクトの形式で操作できる。柔軟性は高い。
以下はAQLでBooksコレクションからArangoDBのタイトルで検索し、関連するpersonを深さ2でグラフ探索している。
FOR book IN Books
FILTER book.title == "ArangoDB"
FOR person IN 2..2 INBOUND book Sales, OUTBOUND People
RETURN person.name
GUIを見ると、ANALYZERSがあったりして機能も充実していそう。
Pulseを見ると、開発はかなりactive。
Dgraph
Dgraph は distributed graph database として設計されており、水平スケーリングに優れる。シャーディングされ、クラスタ内の複数のノードに分散される。GraphQLがベースでクエリを行う。
スキーマの定義から
type User {
username: String! @id
displayName: String
avatarImg: String
posts: [Post!]
comments: [Comment!]
}
type Post {
id: ID!
title: String! @search(by: [term])
text: String! @search(by: [fulltext])
tags: String @search(by: [term])
datePublished: DateTime
author: User! @hasInverse(field: posts)
category: Category! @hasInverse(field: posts)
comments: [Comment!]
}
type Comment {
id: ID!
text: String!
commentsOn: Post! @hasInverse(field: comments)
author: User! @hasInverse(field: comments)
}
type Category {
id: ID!
name: String! @search(by: [term])
posts: [Post!]
}
mutation(やquery)を行う。
mutation {
addUser(input: [
{ username: "User1" }
]) {
user {
username
displayName
}
}
addCategory(input: [
{ name: "Category1",
posts : [
{
title: "Post1",
text: "Post1",
author: { username: "User1" }
},
{
title: "Post2",
text: "Post2",
author: { username: "User1" }
},
{
title: "Post3",
text: "Post3",
author: { username: "User1" }
}
]
}
]) {
category {
id
name
posts { text }
}
}
}
Pulseを見ると開発はactiveではなさそう。
DockerでGraph DBを動かす
Neo4jのセットアップ
1. DockerでNeo4jを動かす。
docker run \
--name neo4j \
-p7474:7474 -p7687:7687 \
-d \
--env NEO4J_AUTH=neo4j/password \
neo4j:latest
GUI へアクセスします。
2.- user/password は neo4j/password です。
ArangoDBのセットアップ
1. DockerでArangoDBを動かす。
docker run -e ARANGO_ROOT_PASSWORD=password -p 8529:8529 -d arangodb/arangodb:latest
GUIへアクセスします。
2.- root/password でログインします。
Dgraphのセットアップ
1. DockerでDgraphを動かす。
docker run -it -p 8080:8080 -p 9080:9080 -d dgraph/standalone:latest
GUIへアクセスします。
2.PythonからGraph DBを操作する
今回は2つのノードと1つのエッジで構成される以下のグラフデータを作成します。
Neo4jでの操作
Neo4jとの連携にはneo4jパッケージを使用します。
1. 接続とDBの作成
from neo4j import GraphDatabase
driver = GraphDatabase.driver("bolt://localhost:7687", auth=("neo4j", "password"))
2. nodeとrelationshipの追加
def create_and_link_nodes(tx):
query = (
"CREATE (a:Person {name: 'Alice'}) "
"CREATE (b:Person {name: 'Bob'}) "
"CREATE (a)-[:LIKES]->(b)"
)
tx.run(query)
def create_friendship():
with driver.session() as session:
session.write_transaction(create_and_link_nodes)
# グラフの作成を実行
create_friendship()
3. Neo4jのGUIへログインしてグラフを見てみる。
ArangoDBでの操作
ArangoDBとの連携にはpython-arangoパッケージを使用します。
1. 接続とDBの作成
from arango import ArangoClient
# ArangoDBサーバーへの接続を初期化
client = ArangoClient(hosts='http://localhost:8529')
# データベースに接続(存在しない場合は作成)
sys_db = client.db('_system', username='root', password='password')
if not sys_db.has_database('mydb'):
sys_db.create_database('mydb')
db = client.db('mydb', username='root', password='password')
2. コレクションを作成
if not db.has_collection('users'):
users = db.create_collection('users')
if not db.has_collection('likes'):
likes = db.create_collection('likes', edge=True)
3. ノードとエッジをコレクションに追加
alice = users.insert({'_key': 'Alice', 'name': 'Alice'})
bob = users.insert({'_key': 'Bob', 'name': 'Bob'})
likes.insert({'_from': alice['_id'], '_to': bob['_id'], 'relation': 'like'})
4. ArangoDBのGUIへmydbでログインしてグラフを見てみる。
Dgraphでの操作
Dgraphとの連携にはpydgraphパッケージを使用します。
1. 接続とDB(mydb)の作成
import pydgraph
client_stub = pydgraph.DgraphClientStub('localhost:9080')
client = pydgraph.DgraphClient(client_stub)
2. スキーマの設定
# スキーマの設定
schema = """
name: string @index(exact) .
type Person {
name
}
"""
client.alter(pydgraph.Operation(schema=schema))
3. ノードとエッジの作成
txn = client.txn()
try:
# ノードの作成
mutation = pydgraph.Mutation(set_nquads='''
_:alice <name> "Alice" .
_:bob <name> "Bob" .
_:charlie <name> "Charlie" .
_:alice <likes> _:bob .
''')
txn.mutate(mutation)
txn.commit()
finally:
txn.discard()
Discussion