其他查询机制
隐式(或自动提交)事务
这是运行 Cypher 查询的最基本和最有限的形式。驱动程序不会自动重试隐式事务,而是会对使用 .executableQuery()
和 托管事务 运行的查询进行重试。只有当其他驱动程序查询接口不适合目的或用于快速原型设计时,才应使用隐式事务。
// import java.util.Map
// import org.neo4j.driver.SessionConfig
try (var session = driver.session(SessionConfig.builder().withDatabase("neo4j").build())) {
session.run("CREATE (a:Person {name: $name})", Map.of("name", "Licia"));
}
隐式事务最晚在会话被销毁时或在同一会话中执行另一个事务之前提交。除此之外,无法明确保证隐式事务在会话生命周期中的确切提交时间。要确保隐式事务提交,可以调用其结果的 .consume()
方法。
由于驱动程序无法确定 Session.run()
调用中的查询是否需要数据库的读或写会话,因此它默认使用写会话。如果您的隐式事务仅包含读查询,则在创建会话时,可以通过配置方法 .withRouting(RoutingControl.READ)
使驱动程序了解,从而获得性能提升。
隐式事务是唯一可用于 CALL { … } IN TRANSACTIONS 查询的事务。.
|
导入 CSV 文件
使用 Session.run()
最常见的用例是使用 LOAD CSV
Cypher 子句将大型 CSV 文件导入数据库,并防止由于事务大小而导致的超时错误。
// import java.util.Map
// import org.neo4j.driver.SessionConfig
try (var session = driver.session(SessionConfig.builder().withDatabase("neo4j").build())) {
var 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
""");
var summary = result.consume();
System.out.println(summary.counters());
}
虽然 LOAD CSV 可能很方便,但将 CSV 文件的解析推迟到 Java 应用程序并避免 LOAD CSV 并没有什么错误。实际上,将解析逻辑移动到应用程序可以使您更好地控制导入过程。有关有效的批量数据插入,请参阅 性能 → 批量数据创建. |
有关更多信息,请参阅 Cypher → 子句 → LOAD CSV.
事务配置
可以通过提供一个 TransactionConfig
对象作为 Session.run()
调用的可选最后一个参数,对隐式事务进行进一步控制。配置回调允许指定查询超时并向事务附加元数据。有关更多信息,请参阅 事务 → 事务配置.
// import java.util.Map
// import java.time.Duration
// import org.neo4j.driver.SessionConfig
// import org.neo4j.driver.TransactionConfig
try (var session = driver.session(SessionConfig.builder().withDatabase("neo4j").build())) {
var result = session.run("CREATE (a:Person {name: $name})", Map.of("name", "John"),
TransactionConfig.builder()
.withTimeout(Duration.ofSeconds(5))
.withMetadata(Map.of("appName", "peopleTracker"))
.build()
);
}
属性键、关系类型和标签中的动态值
通常,不应将参数直接连接到查询中,而应使用 查询参数。但是,在某些情况下,查询结构可能会阻止在所有部分中使用参数。实际上,虽然参数可用于文字和表达式以及节点和关系 ID,但它们不能用于以下构造
-
属性键,因此
MATCH (n) WHERE n.$param = 'something'
无效; -
关系类型,因此
MATCH (n)-[:$param]→(m)
无效; -
标签,因此
MATCH (n:$param)
无效。
对于这些查询,您被迫使用字符串连接。为了防止 Cypher 注入,您应该将动态值放在反引号中并自行转义。请注意,Cypher 处理 Unicode,因此也要注意 Unicode 文字 \u0060
。
// import org.neo4j.driver.QueryConfig;
var label = "Person\\u0060n";
// convert \u0060 to literal backtick and then escape backticks
var escapedLabel = label.replace("\\u0060", "`").replace("`", "``");
var result = driver.executableQuery("MATCH (p:`" + escapedLabel + "` {name: $name}) RETURN p.name")
.withParameters(Map.of("name", "Alice"))
.withConfig(QueryConfig.builder().withDatabase("neo4j").build())
.execute();
另一种避免字符串连接的解决方法是使用 APOC 过程,例如 apoc.merge.node
,它支持动态标签和属性键。
apoc.merge.node
创建具有动态标签/属性键的节点。// import org.neo4j.driver.QueryConfig;
String propertyKey = "name";
String label = "Person";
var result = driver.executableQuery("CALL apoc.merge.node($labels, $properties)")
.withParameters(Map.of("labels", List.of(label), "properties", Map.of(propertyKey, "Alice")))
.withConfig(QueryConfig.builder().withDatabase("neo4j").build())
.execute();
如果您在 Docker 中运行 Neo4j,则在启动容器时需要启用 APOC。请参阅 APOC → 安装 → Docker. |
词汇表
- 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
. - 事务
-
事务是工作单元,它要么全部提交,要么在发生故障时回滚。例如,银行转账:它包含多个步骤,但它们必须全部成功或被恢复,以避免从一个帐户中扣除资金而没有添加到另一个帐户中。
- 背压
-
背压是阻碍数据流的力。它确保客户端不会被其无法处理的快速数据所淹没。
- 事务函数
-
事务函数是
executeRead
或executeWrite
调用执行的回调。如果发生服务器故障,驱动程序会自动重新执行回调。 - 驱动程序
-
一个
Driver
对象包含建立与 Neo4j 数据库连接所需的详细信息。