更进一步的查询机制
隐式(或自动提交)事务
这是运行 Cypher 查询最基本也是最有限的形式。驱动程序不会自动重试隐式事务,因为它会对使用 execute_query()
和 管理事务 运行的查询执行。只有在其他驱动程序查询接口不适合目的或用于快速原型设计时,才应使用隐式事务。
使用 Session.run()
方法运行隐式事务。它返回一个 Result
对象,需要进行 相应处理。
with driver.session(database="neo4j") as session:
session.run("CREATE (a:Person {name: $name})", name="Licia")
隐式事务在会话被销毁或在同一个会话中执行另一个事务之前,最迟 会被提交。除此之外,在会话的生命周期中,没有明确的保证何时确切地提交隐式事务。要确保提交隐式事务,可以在其结果上调用 .consume()
方法。
由于驱动程序无法确定 session.run()
调用中的查询是否需要与数据库进行读或写会话,因此它默认为写。如果您的隐式事务仅包含读查询,则在创建会话时设置关键字参数 default_access_mode=neo4j.READ_ACCESS
可以提高 性能。
隐式事务是唯一可用于 CALL { … } IN TRANSACTIONS 查询的事务。.
|
导入 CSV 文件
使用 Session.run()
的最常见用例是使用 LOAD CSV
Cypher 子句将大型 CSV 文件导入数据库,并防止由于事务大小导致的超时错误。
with driver.session(database="neo4j") as session:
result = session.run("""
LOAD CSV FROM 'https://data.neo4j.com/bands/artists.csv' AS line
CALL {
WITH line
MERGE (:Artist {name: line[1], age: toInteger(line[2])})
} IN TRANSACTIONS OF 2 ROWS
""")
print(result.consume().counters)
虽然 LOAD CSV 可能很方便,但将 CSV 文件的解析推迟到您的 Python 应用程序中并没有什么错误,并且可以避免 LOAD CSV 。事实上,将解析逻辑移到应用程序中可以使您更好地控制导入过程。有关高效的批量数据插入,请参阅 性能 → 批量数据创建。 |
有关更多信息,请参阅 Cypher → 子句 → Load CSV。
事务配置
Query
对象允许指定查询超时并向事务附加元数据。元数据在服务器日志中可见(如 unit_of_work
装饰器所述)。
from neo4j import Query
with driver.session(database="neo4j") as session:
query = Query("CREATE (a:Person {name: $name})",
timeout=1.0,
metadata={"app_name": "people"})
result = session.run(query, name="John")
属性键、关系类型和标签中的动态值
一般情况下,您不应将参数直接连接到查询中,而应使用 查询参数。但是,在某些情况下,您的查询结构可能无法在所有部分使用参数。事实上,虽然参数可以用于文字和表达式以及节点和关系 ID,但它们不能用于以下结构
-
属性键,因此
MATCH (n) WHERE n.$param = 'something'
无效; -
关系类型,因此
MATCH (n)-[:$param]→(m)
无效; -
标签,因此
MATCH (n:$param)
无效。
对于这些查询,您被迫使用字符串连接。为了防止 link:Cypher 注入,您应该将动态值括在反引号中,并自行对其进行转义。请注意,Cypher 处理 Unicode,因此也要注意 Unicode 文字 \u0060
。
label = "Person\\u0060n"
# convert \u0060 to literal backtick and then escape backticks
escaped_label = label.replace("\\u0060", "`").replace("`", "``")
driver.execute_query(
f"MATCH (p:`{escaped_label}` {{name: $name}}) RETURN p.name",
name="Alice",
database_="neo4j"
)
另一种避免字符串连接的解决方法是使用 APOC 过程,例如 apoc.merge.node
,它支持动态标签和属性键。
apoc.merge.node
创建具有动态标签/属性键的节点。property_key = "name"
label = "Person"
driver.execute_query(
"CALL apoc.merge.node($labels, $properties)",
labels=[label], properties={property_key: "Alice"},
database_="neo4j"
)
如果您在 Docker 中运行 Neo4j,则需要在启动容器时启用 APOC。请参阅 APOC → 安装 → Docker。 |
日志记录
驱动程序通过本机 logging
库将消息记录到名为 neo4j
的记录器。要将日志消息重定向到标准输出,请使用 watch 函数
import sys
from neo4j.debug import watch
watch("neo4j", out=sys.stdout)
[DEBUG ] [Thread 139807941394432] [Task None ] 2023-03-31 09:31:39,616 [#0000] _: <POOL> created, routing address IPv4Address(('localhost', 7687))
[DEBUG ] [Thread 139807941394432] [Task None ] 2023-03-31 09:31:39,616 [#0000] _: <POOL> acquire routing connection, access_mode='WRITE', database='neo4j'
[DEBUG ] [Thread 139807941394432] [Task None ] 2023-03-31 09:31:39,616 [#0000] _: <ROUTING> checking table freshness (readonly=False): table expired=True, has_server_for_mode=False, table routers={IPv4Address(('localhost', 7687))} => False
[DEBUG ] [Thread 139807941394432] [Task None ] 2023-03-31 09:31:39,616 [#0000] _: <POOL> attempting to update routing table from IPv4Address(('localhost', 7687))
[DEBUG ] [Thread 139807941394432] [Task None ] 2023-03-31 09:31:39,616 [#0000] _: <RESOLVE> in: localhost:7687
[DEBUG ] [Thread 139807941394432] [Task None ] 2023-03-31 09:31:39,617 [#0000] _: <RESOLVE> dns resolver out: 127.0.0.1:7687
[DEBUG ] [Thread 139807941394432] [Task None ] 2023-03-31 09:31:39,617 [#0000] _: <POOL> _acquire router connection, database='neo4j', address=ResolvedIPv4Address(('127.0.0.1', 7687))
[DEBUG ] [Thread 139807941394432] [Task None ] 2023-03-31 09:31:39,617 [#0000] _: <POOL> trying to hand out new connection
[DEBUG ] [Thread 139807941394432] [Task None ] 2023-03-31 09:31:39,617 [#0000] C: <OPEN> 127.0.0.1:7687
[DEBUG ] [Thread 139807941394432] [Task None ] 2023-03-31 09:31:39,619 [#AF18] C: <MAGIC> 0x6060B017
[DEBUG ] [Thread 139807941394432] [Task None ] 2023-03-31 09:31:39,619 [#AF18] C: <HANDSHAKE> 0x00000005 0x00020404 0x00000104 0x00000003
[DEBUG ] [Thread 139807941394432] [Task None ] 2023-03-31 09:31:39,620 [#AF18] S: <HANDSHAKE> 0x00000005
[DEBUG ] [Thread 139807941394432] [Task None ] 2023-03-31 09:31:39,620 [#AF18] C: HELLO {'user_agent': 'neo4j-python/5.6.0 Python/3.10.6-final-0 (linux)', 'routing': {'address': 'localhost:7687'}, 'scheme': 'basic', 'principal': 'neo4j', 'credentials': '*******'}
词汇表
- LTS
-
长期支持 版本是保证支持数年时间的版本。Neo4j 4.4 是 LTS,Neo4j 5 也将有一个 LTS 版本。
- Aura
-
Aura 是 Neo4j 的完全托管云服务。它提供免费和付费计划。
- Cypher
-
Cypher 是 Neo4j 的图查询语言,它允许您从数据库中检索数据。它类似于 SQL,但用于图。
- APOC
-
Cypher 上的强大过程 (APOC) 是一个包含(许多)函数的库,这些函数无法在 Cypher 本身中轻松表达。
- Bolt
-
Bolt 是用于 Neo4j 实例和驱动程序之间交互的协议。默认情况下,它监听端口 7687。
- ACID
-
原子性、一致性、隔离性、持久性 (ACID) 是保证数据库事务可靠处理的属性。符合 ACID 的 DBMS 确保数据库中的数据即使在出现故障的情况下也能保持准确和一致。
- 最终一致性
-
如果数据库保证所有集群成员将在某个时间点 存储数据的最新版本,则该数据库是最终一致的。
- 因果一致性
-
如果数据库保证每个集群成员以相同的顺序看到读写查询,则该数据库是因果一致的。这比最终一致性 更强。
- NULL
-
空标记不是一种类型,而是表示值不存在的占位符。有关更多信息,请参阅 Cypher → 使用
null
。 - 事务
-
事务是工作单元,它要么全部提交,要么在失败时回滚。例如银行转账:它涉及多个步骤,但必须全部成功或回滚,以避免从一个帐户中减去钱,而没有添加到另一个帐户中。
- 背压
-
背压是阻碍数据流的力。它确保客户端不会被它无法处理的速度过快的数据淹没。
- 事务函数
-
事务函数是由
execute_read
或execute_write
调用执行的回调。如果出现服务器故障,驱动程序会自动重新执行回调。 - 驱动程序
-
一个
Driver
对象包含建立与 Neo4j 数据库连接所需的详细信息。