操作查询结果

本节展示如何处理查询结果,以提取最适合您应用程序的数据形式。

结果作为列表

默认情况下,Driver.execute_query() 返回一个 EagerResult 对象。

records, summary, keys = driver.execute_query(
    "MATCH (a:Person) RETURN a.name AS name, a.age AS age",
    database_="neo4j",
)
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

驱动程序可以将结果转换为 Pandas DataFrame。为此,请使用 .execute_query() 关键字参数 result_transformer_ 并将其设置为 neo4j.Result.to_df。此方法仅在安装了 pandas 库时可用。

返回一个包含两列 (n, m) 和 10 行的 DataFrame
import neo4j

pandas_df = driver.execute_query(
    "UNWIND range(1, 10) AS n RETURN n, n+1 AS m",
    database_="neo4j",
    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)

转换为图

驱动程序可以将结果转换为图对象集合。为此,请使用 .execute_query() 关键字参数 result_transformer_ 并将其设置为 neo4j.Result.graph。为了最大限度地利用此方法,您的查询应返回图状结果而非单列。图转换器返回一个 Graph 对象,该对象公开 nodesrelationships 属性,这些属性是 NodeRelationship 对象的集合视图。

您可以使用图格式进行进一步处理或可视化查询结果。下面是一个使用 pyvis 库绘制图的示例实现。

使用 pyvis 可视化图结果
import pyvis
from neo4j import GraphDatabase
import neo4j


URI = "{neo4j-database-uri}"
AUTH = ("{neo4j-username}", "{neo4j-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_="neo4j",
        )

        # 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_="neo4j",
        )

        # 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()
pyvis example
图 1. 上述示例的图可视化

自定义转换器

对于更高级的场景,您可以使用参数 result_transformer_ 提供一个自定义函数,以进一步操作查询产生的 Result 对象。转换器接受一个 Result 对象,并可以输出任何数据结构。转换器的返回值又由 .execute_query() 返回。

在转换器函数内部,您可以使用 Result 的任何方法

使用 singleconsume 的自定义转换器
# 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_="neo4j",
    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))
使用 fetchpeek 的自定义转换器
# 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_="neo4j",
    result_transformer_=exactly_5,
)

转换器不得返回 Result 对象本身。这样做大致等同于返回一个指向结果缓冲区的指针,一旦查询事务结束,该指针就会失效。

def transformer(result):
    return result

result = driver.execute_query(
    "MATCH (a:Person) RETURN a.name",
    result_transformer_=transformer)
print(result)
print(result.single())
neo4j.exceptions.ResultConsumedError: The result is out of scope.
The associated transaction has been closed.
Results can only be used while the transaction is open.

术语表

LTS

长期支持 (LTS) 版本是保证支持多年的版本。Neo4j 4.4 是 LTS 版本,Neo4j 5 也将有一个 LTS 版本。

Aura

Aura 是 Neo4j 的全托管云服务。它提供免费和付费计划。

Cypher

Cypher 是 Neo4j 的图查询语言,它允许您从数据库中检索数据。它类似于 SQL,但适用于图。

APOC

Awesome Procedures On Cypher (APOC) 是一个函数库(包含许多函数),这些函数本身无法轻易地用 Cypher 表达。

Bolt

Bolt 是 Neo4j 实例与驱动程序之间交互所使用的协议。它默认监听端口 7687。

ACID

原子性、一致性、隔离性、持久性 (ACID) 是保证数据库事务可靠处理的属性。符合 ACID 的 DBMS 确保数据库中的数据在发生故障时仍能保持准确和一致。

最终一致性

如果数据库提供所有集群成员将在某个时间点存储最新版本数据的保证,则称其为最终一致性数据库。

因果一致性

如果集群的每个成员都以相同的顺序看到读写查询,则数据库是因果一致的。这比最终一致性更强。

NULL

空标记不是一种类型,而是值缺失的占位符。更多信息请参阅 Cypher → 使用 null

事务

事务是作为一个整体提交或在失败时回滚的工作单元。一个例子是银行转账:它涉及多个步骤,但所有步骤都必须成功或被撤销,以避免资金从一个账户中扣除但未添加到另一个账户的情况。

背压

背压是阻碍数据流的一种力。它确保客户端不会被快于其处理速度的数据所淹没。

事务函数

事务函数是由 execute_readexecute_write 调用执行的回调。在服务器故障时,驱动程序会自动重新执行该回调。

Driver

一个 Driver 对象包含与 Neo4j 数据库建立连接所需的详细信息。

© . All rights reserved.