操作查询结果
本节介绍如何处理查询结果,以便以最适合您应用程序的形式提取数据。
作为列表的结果
默认情况下,Driver.execute_query() 返回一个 EagerResult 对象。
records, summary, keys = driver.execute_query(
"MATCH (a:Person) RETURN a.name AS name, a.age AS age",
database_="<database-name>",
)
for person in records: (1)
print(person)
# person["name"] or person["age"] are also valid
# Some summary information (2)
print("Query `{query}` returned {records_count} records in {time} ms.".format(
query=summary.query, records_count=len(records),
time=summary.result_available_after
))
print(f"Available keys are {keys}") # ['name', 'age'] (3)
| 1 | 结果记录以列表形式呈现。 |
| 2 | 执行摘要,包含元数据和有关结果的信息。 |
| 3 | 返回行中可用的 keys(键)。 |
转换为 Pandas DataFrame
驱动程序可以通过设置 result_transformer_=neo4j.Result.to_df 将结果转换为 Pandas DataFrame。此方法需要安装 pandas 库。
n, m) 和 10 行的 DataFrameimport neo4j
pandas_df = driver.execute_query(
"UNWIND range(1, 10) AS n RETURN n, n+1 AS m",
database_="<database-name>",
result_transformer_=neo4j.Result.to_df
)
print(type(pandas_df)) # <class 'pandas.core.frame.DataFrame'>
此转换器接受两个可选参数
-
expand— 如果为True,结果中的某些数据结构将被递归展开并扁平化。更多信息请参阅 API 文档。 -
parse_dates— 如果为True,则仅包含time.DateTime对象、time.Date对象或None的列将被转换为pandas.Timestamp。
要将参数传递给 to_df,请使用 lambda 函数result_transformer_=lambda res: res.to_df(True)
|
转换为图形
驱动程序可以通过设置 result_transformer_=neo4j.Result.graph 将结果转换为图形对象集合。为了充分利用此方法,您的查询应该返回图形类型的结果,而不是单列结果。图形转换器返回一个 Graph 对象,该对象公开了 nodes 和 relationships 属性,它们分别是 Node 和 Relationship 对象的集合视图。
您可以将图形格式用于进一步的处理或可视化查询结果。下面是一个使用 pyvis 库绘制图形的示例实现。
pyvis 可视化图形结果import pyvis
from neo4j import GraphDatabase
import neo4j
URI = "<database-uri>"
AUTH = ("<username>", "<password>")
def main():
with GraphDatabase.driver(URI, auth=AUTH) as driver:
# Create some friends
input_list = [("Arthur", "Guinevre"),
("Arthur", "Lancelot"),
("Arthur", "Merlin")]
driver.execute_query("""
UNWIND $pairs AS pair
MERGE (a:Person {name: pair[0]})
MERGE (a)-[:KNOWS]->(friend:Person {name: pair[1]})
""", pairs=input_list,
database_="<database-name>",
)
# Create a film
driver.execute_query("""
MERGE (film:Film {title: $title})
MERGE (liker:Person {name: $person_name})
MERGE (liker)-[:LIKES]->(film)
""", title="Wall-E", person_name="Arthur",
database_="<database-name>",
)
# Query to get a graphy result
graph_result = driver.execute_query("""
MATCH (a:Person {name: $name})-[r]-(b)
RETURN a, r, b
""", name="Arthur",
result_transformer_=neo4j.Result.graph,
)
# Draw graph
nodes_text_properties = { # what property to use as text for each node
"Person": "name",
"Film": "title",
}
visualize_result(graph_result, nodes_text_properties)
def visualize_result(query_graph, nodes_text_properties):
visual_graph = pyvis.network.Network()
for node in query_graph.nodes:
node_label = list(node.labels)[0]
node_text = node[nodes_text_properties[node_label]]
visual_graph.add_node(node.element_id, node_text, group=node_label)
for relationship in query_graph.relationships:
visual_graph.add_edge(
relationship.start_node.element_id,
relationship.end_node.element_id,
title=relationship.type
)
visual_graph.show('network.html', notebook=False)
if __name__ == "__main__":
main()
自定义转换器
对于更高级的场景,您可以使用 result_transformer_ 参数提供一个自定义函数,以进一步操作查询产生的 Result 对象。转换器接收一个 Result 对象,并可以输出任何数据结构。转换器的返回值将由 .execute_query() 返回。
在转换器函数内部,您可以使用 任何 Result 方法。
single 和 consume 的自定义转换器# Get a single record (or an exception) and the summary from a result.
def get_single_person(result):
record = result.single(strict=True)
summary = result.consume()
return record, summary
record, summary = driver.execute_query(
"MERGE (a:Person {name: $name}) RETURN a.name AS name",
name="Alice",
database_="<database-name>",
result_transformer_=get_single_person,
)
print("The query `{query}` returned {record} in {time} ms.".format(
query=summary.query, record=record, time=summary.result_available_after))
fetch 和 peek 的自定义转换器# Get exactly 5 records, or an exception.
def exactly_5(result):
records = result.fetch(5)
if len(records) != 5:
raise Exception(f"Expected exactly 5 records, found only {len(records)}.")
if result.peek():
raise Exception("Expected exactly 5 records, found more.")
return records
records = driver.execute_query("""
UNWIND ['Alice', 'Bob', 'Laura', 'John', 'Patricia'] AS name
MERGE (a:Person {name: name}) RETURN a.name AS name
""", database_="<database-name>",
result_transformer_=exactly_5,
)
|
转换器不得返回
|
术语表
- LTS (长期支持版)
-
长期支持 (Long Term Support) 版本是保证在若干年内得到支持的版本。Neo4j 4.4 和 5.26 是 LTS 版本。
- Aura
-
Aura 是 Neo4j 的全托管云服务。它提供免费和付费计划。
- Cypher
-
Cypher 是 Neo4j 的图查询语言,允许您从数据库中检索数据。它就像 SQL,但专用于图数据库。
- APOC
-
Awesome Procedures On Cypher (APOC) 是一个包含(许多)函数的库,这些函数在 Cypher 本身中难以轻松实现。
- Bolt
-
Bolt 是用于 Neo4j 实例和驱动程序之间交互的协议。默认监听 7687 端口。
- ACID
-
原子性 (Atomicity)、一致性 (Consistency)、隔离性 (Isolation)、持久性 (Durability) (ACID) 是保证数据库事务可靠处理的属性。符合 ACID 的 DBMS 确保即使发生故障,数据库中的数据也能保持准确和一致。
- 最终一致性
-
如果一个数据库能保证所有集群成员在某个时间点都存储了数据的最新版本,则该数据库具有最终一致性。
- 因果一致性
-
如果读写查询被集群中的每个成员以相同的顺序看到,则数据库具有因果一致性。这比最终一致性更强。
- NULL
-
空标记不是一种类型,而是缺失值的占位符。更多信息,请参阅 Cypher → 使用
null。 - 事务
-
事务是一个工作单元,要么被提交,要么在失败时被回滚。例如银行转账:它涉及多个步骤,但它们必须全部成功或全部撤销,以避免钱从一个账户扣除却未存入另一个账户的情况。
- 背压
-
背压是对数据流的抵抗力。它确保客户端不会被过快发送的数据压垮,从而超出其处理能力。
- 书签
-
书签是代表数据库某种状态的标记。通过将一个或多个书签与查询一起传递,服务器将确保在所表示的状态建立之前,该查询不会被执行。
- 事务函数
-
事务函数是由
execute_read或execute_write调用执行的回调。如果发生服务器故障,驱动程序会自动重新执行该回调。 - 驱动程序 (Driver)
-
一个
Driver对象保存了与 Neo4j 数据库建立连接所需的详细信息。