从 neo4j 查询结果构建 NetworkX 图?
Constructing NetworkX graph from neo4j query result?
我正在尝试了解如何查询 neo4j 数据库,并将结果转换为 networkx 图。我可以查询(电影图)数据库并获得结果,但我可以找到一种简单的方法将结果转换为 networkx 图。是否可以执行以下操作?
from neo4j import GraphDatabase
import networkx as nx
driver = GraphDatabase.driver('bolt://localhost:7687', auth=("neo4j", "hunter2"))
query = """
MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
WHERE toLower(m.title) CONTAINS "you"
RETURN *
"""
with driver.session() as session:
result = session.run(query)
# This bit doesn't work
G = nx.Graph(result)
我在网上找到的一些尝试性解决方案都没有成功,最后我自己为此编写了一个函数。将它张贴在这里以防对任何人有帮助。
这通过迭代结果来工作,确定遇到的每个条目是节点还是关系(边),如果尚未添加,则将其添加到图中。我是 cypher/neo4j 的新手,不确定 Node/Relation 是否详尽无遗,所以目前我只是在遇到任何其他问题时提出错误。
from neo4j import GraphDatabase
from neo4j.types.graph import Node, Relationship
import pandas as pd
import networkx as nx
def graph_from_cypher(data):
"""Constructs a networkx graph from the results of a neo4j cypher query.
Example of use:
>>> result = session.run(query)
>>> G = graph_from_cypher(result.data())
Nodes have fields 'labels' (frozenset) and 'properties' (dicts). Node IDs correspond to the neo4j graph.
Edges have fields 'type_' (string) denoting the type of relation, and 'properties' (dict)."""
G = nx.MultiDiGraph()
def add_node(node):
# Adds node id it hasn't already been added
u = node.id
if G.has_node(u):
return
G.add_node(u, labels=node._labels, properties=dict(node))
def add_edge(relation):
# Adds edge if it hasn't already been added.
# Make sure the nodes at both ends are created
for node in (relation.start_node, relation.end_node):
add_node(node)
# Check if edge already exists
u = relation.start_node.id
v = relation.end_node.id
eid = relation.id
if G.has_edge(u, v, key=eid):
return
# If not, create it
G.add_edge(u, v, key=eid, type_=relation.type, properties=dict(relation))
for d in data:
for entry in d.values():
# Parse node
if isinstance(entry, Node):
add_node(entry)
# Parse link
elif isinstance(entry, Relationship):
add_edge(entry)
else:
raise TypeError("Unrecognized object")
return G
driver = GraphDatabase.driver('bolt://localhost:7687', auth=("neo4j", "hunter2"))
query = """
MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
WHERE toLower(m.title) CONTAINS "you"
RETURN *
"""
with driver.session() as session:
result = session.run(query)
# This works
G = graph_from_cypher(result.data())
这是一个更紧凑的代码:
from neo4j import GraphDatabase
import networkx as nx
driver = GraphDatabase.driver('bolt://localhost:7687', auth=("neo4j", "neo4jj"))
query = """
MATCH (n)-[r]->(c) RETURN *
"""
results = driver.session().run(query)
G = nx.MultiDiGraph()
nodes = list(results.graph()._nodes.values())
for node in nodes:
G.add_node(node.id, labels=node._labels, properties=node._properties)
rels = list(results.graph()._relationships.values())
for rel in rels:
G.add_edge(rel.start_node.id, rel.end_node.id, key=rel.id, type=rel.type, properties=rel._properties)
请记住,MATCH (n)-[r]->(c) RETURN *
查询可能无法检索整个 neo4j 图,因为未连接的节点将被忽略。如果您需要包含未连接节点的整个图,请从 MATCH (n) RETURN n
查询的结果中添加节点,然后从 MATCH (n)-[r]->(c) RETURN *
添加关系
我正在尝试了解如何查询 neo4j 数据库,并将结果转换为 networkx 图。我可以查询(电影图)数据库并获得结果,但我可以找到一种简单的方法将结果转换为 networkx 图。是否可以执行以下操作?
from neo4j import GraphDatabase
import networkx as nx
driver = GraphDatabase.driver('bolt://localhost:7687', auth=("neo4j", "hunter2"))
query = """
MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
WHERE toLower(m.title) CONTAINS "you"
RETURN *
"""
with driver.session() as session:
result = session.run(query)
# This bit doesn't work
G = nx.Graph(result)
我在网上找到的一些尝试性解决方案都没有成功,最后我自己为此编写了一个函数。将它张贴在这里以防对任何人有帮助。
这通过迭代结果来工作,确定遇到的每个条目是节点还是关系(边),如果尚未添加,则将其添加到图中。我是 cypher/neo4j 的新手,不确定 Node/Relation 是否详尽无遗,所以目前我只是在遇到任何其他问题时提出错误。
from neo4j import GraphDatabase
from neo4j.types.graph import Node, Relationship
import pandas as pd
import networkx as nx
def graph_from_cypher(data):
"""Constructs a networkx graph from the results of a neo4j cypher query.
Example of use:
>>> result = session.run(query)
>>> G = graph_from_cypher(result.data())
Nodes have fields 'labels' (frozenset) and 'properties' (dicts). Node IDs correspond to the neo4j graph.
Edges have fields 'type_' (string) denoting the type of relation, and 'properties' (dict)."""
G = nx.MultiDiGraph()
def add_node(node):
# Adds node id it hasn't already been added
u = node.id
if G.has_node(u):
return
G.add_node(u, labels=node._labels, properties=dict(node))
def add_edge(relation):
# Adds edge if it hasn't already been added.
# Make sure the nodes at both ends are created
for node in (relation.start_node, relation.end_node):
add_node(node)
# Check if edge already exists
u = relation.start_node.id
v = relation.end_node.id
eid = relation.id
if G.has_edge(u, v, key=eid):
return
# If not, create it
G.add_edge(u, v, key=eid, type_=relation.type, properties=dict(relation))
for d in data:
for entry in d.values():
# Parse node
if isinstance(entry, Node):
add_node(entry)
# Parse link
elif isinstance(entry, Relationship):
add_edge(entry)
else:
raise TypeError("Unrecognized object")
return G
driver = GraphDatabase.driver('bolt://localhost:7687', auth=("neo4j", "hunter2"))
query = """
MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
WHERE toLower(m.title) CONTAINS "you"
RETURN *
"""
with driver.session() as session:
result = session.run(query)
# This works
G = graph_from_cypher(result.data())
这是一个更紧凑的代码:
from neo4j import GraphDatabase
import networkx as nx
driver = GraphDatabase.driver('bolt://localhost:7687', auth=("neo4j", "neo4jj"))
query = """
MATCH (n)-[r]->(c) RETURN *
"""
results = driver.session().run(query)
G = nx.MultiDiGraph()
nodes = list(results.graph()._nodes.values())
for node in nodes:
G.add_node(node.id, labels=node._labels, properties=node._properties)
rels = list(results.graph()._relationships.values())
for rel in rels:
G.add_edge(rel.start_node.id, rel.end_node.id, key=rel.id, type=rel.type, properties=rel._properties)
请记住,MATCH (n)-[r]->(c) RETURN *
查询可能无法检索整个 neo4j 图,因为未连接的节点将被忽略。如果您需要包含未连接节点的整个图,请从 MATCH (n) RETURN n
查询的结果中添加节点,然后从 MATCH (n)-[r]->(c) RETURN *