运行非阻塞异步查询

查询数据库运行您自己的事务中的示例使用了驱动程序的同步形式:当针对数据库运行查询时,您的应用程序会等待服务器检索所有结果并将其传输给驱动程序。对于大多数用例来说这不是问题,但对于处理时间较长或结果集较大的查询,异步处理可以加速您的应用程序。

异步托管事务

您可以通过 AsyncSession 运行异步事务。其流程与常规事务类似,不同之处在于异步事务函数返回一个 CompletionStage 对象(该对象可进一步转换为 CompletableFuture)。

package demo;

import java.util.Map;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

import org.neo4j.driver.async.AsyncSession;
import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;
import org.neo4j.driver.summary.ResultSummary;
import org.neo4j.driver.SessionConfig;

public class App {

    public static void main(String... args) throws ExecutionException, InterruptedException {
        final String dbUri = "<database-uri>";
        final String dbUser = "<username>";
        final String dbPassword = "<password>";

        try (var driver = GraphDatabase.driver(dbUri, AuthTokens.basic(dbUser, dbPassword))) {  (1)
            driver.verifyConnectivity();

            var summary = printAllPeople(driver);
            // Block as long as necessary (for demonstration purposes)
            System.out.println(summary.get());  (8)
        }
    }

    public static CompletableFuture<ResultSummary> printAllPeople(Driver driver) {
        var session = driver.session(AsyncSession.class, SessionConfig.builder().withDatabase("<database-name>").build());  (2)

        var query = """
        UNWIND ['Alice', 'Bob', 'Sofia', 'Charles'] AS name
        MERGE (p:Person {name: name}) RETURN p.name
        """;
        var summary = session.executeWriteAsync(tx -> tx.runAsync(query)  (3)
                .thenCompose(resCursor -> resCursor.forEachAsync(record -> {  (4)
                    System.out.println(record.get(0).asString());
                })))
            .whenComplete((result, error) -> {  (5)
                session.closeAsync();
            })
            .toCompletableFuture();  (6)

        return summary;  (7)
    }
}
1 驱动程序的创建在同步和异步版本中是一样的。
2 通过将 AsyncSession.class 作为第一个参数提供给 Driver.session() 来创建异步会话,该方法返回一个 AsyncSession 对象。请注意,异步会话不能使用 try 语句作为资源打开,因为驱动程序无法确定何时关闭它们才是安全的。
3 与常规事务一样,.executeWriteAsync()(和 executeReadAsync())接收一个事务函数回调。在事务函数内部,使用 .runAsync() 运行查询。每次查询运行都会返回一个 CompletionStage
4 可以选择使用 CompletionStage 上的方法来处理异步运行程序中的结果。查询的结果集以 async.ResultCursor 的形式提供,它实现了一组类似于同步事务处理结果的方法(请参阅 事务 → 处理查询结果)。
内部对象类型与同步情况相同(例如 RecordResultSummary)。
5 可以选择在查询完成后运行操作,例如关闭驱动程序会话。
6 CompletableFuture 是一种方便返回给调用者的类型。
7 与同步事务相反,.executeWriteAsync().executeReadAsync() 仅返回结果摘要,因此您必须在异步运行程序内部处理结果。
8 .get() 会根据需要等待 future 完成,然后返回其结果。

术语表

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

事务

事务是一个工作单元,要么被提交,要么在失败时被回滚。例如银行转账:它涉及多个步骤,但它们必须全部成功或全部撤销,以避免钱从一个账户扣除却未存入另一个账户的情况。

背压

背压是对数据流的抵抗力。它确保客户端不会被过快发送的数据压垮,从而超出其处理能力。

书签

书签是代表数据库某种状态的标记。通过将一个或多个书签与查询一起传递,服务器将确保在所表示的状态建立之前,该查询不会被执行。

事务函数

事务函数是由 executeReadexecuteWrite 调用执行的回调。如果发生服务器故障,驱动程序会自动重新执行该回调。

驱动程序 (Driver)

Driver 对象保存了与 Neo4j 数据库建立连接所需的详细信息。