

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 适用于 Node.js 的 Amazon QLDB 驱动程序 — 快速入门教程
<a name="driver-quickstart-nodejs"></a>

**重要**  
终止支持通知：现有客户将能够使用 Amazon QLDB，直到 2025 年 7 月 31 日终止支持。有关更多详细信息，请参阅[将亚马逊 QLDB 账本迁移到亚马逊 Aurora PostgreSQL](https://aws.amazon.com/blogs/database/migrate-an-amazon-qldb-ledger-to-amazon-aurora-postgresql/)。

在本教程中，您将学习如何使用适用于 Node.js 的 Amazon QLDB 驱动程序来设置简单应用程序。本指南包括安装驱动程序的步骤，以及基本*创建、读取、更新 JavaScript 和删除 (CRUD) 操作的简短和 TypeScript *代码示例。有关在完整示例应用程序中演示这些操作的更深入的示例，请参阅 [Node.js 教程](getting-started.nodejs.tutorial.md)。

**注意**  
在适用的情况下，某些步骤对于 Node.js 的 QLDB 驱动程序的每个支持主要版本都配备不同代码示例。

**Topics**
+ [先决条件](#driver-quickstart-nodejs.prereqs)
+ [第 1 步：设置您的 项目](#driver-quickstart-nodejs.step-1)
+ [第 2 步：初始化驱动程序](#driver-quickstart-nodejs.step-2)
+ [第 3 步：创建表和索引](#driver-quickstart-nodejs.step-3)
+ [第 4 步：插入文档](#driver-quickstart-nodejs.step-4)
+ [第 5 步：查询文档](#driver-quickstart-nodejs.step-5)
+ [第 6 步：更新文档](#driver-quickstart-nodejs.step-6)
+ [运行完整的应用程序](#driver-quickstart-nodejs.complete)

## 先决条件
<a name="driver-quickstart-nodejs.prereqs"></a>

在开始之前，请务必执行以下操作：

1. 请为 Node.js 驱动程序完成（[先决条件](getting-started.nodejs.md#getting-started.nodejs.prereqs)如果尚未执行此操作）。这包括注册 AWS、授予开发所需的编程访问权限以及安装 Node.js。

1. 创建一个名为 `quick-start` 分类账。

   要了解如何创建分类账，请参阅*控制台入门*中的 [Amazon QLDB 分类账的基本操作](ledger-management.basics.md) 或 [第 1 步：创建新分类账](getting-started-step-1.md)。

如果您正在使用 TypeScript，则还必须执行以下设置步骤。

### 使用 TypeScript
<a name="driver-quickstart-nodejs.prereqs.ts"></a>

**要安装 TypeScript**

1. 安装 TypeScript 软件包。QLDB 驱动程序在 3.8.x 上运行。 TypeScript 

   ```
   $ npm install --global typescript@3.8.0
   ```

1. 安装软件包后，运行以下命令以确保 TypeScript 编译器已安装。

   ```
   $ tsc --version
   ```

要按以下步骤运行代码，请注意必须先将 TypeScript 文件转换为可执行 JavaScript 代码，如下所示。

```
$ tsc app.ts; node app.js
```

## 第 1 步：设置您的 项目
<a name="driver-quickstart-nodejs.step-1"></a>

首先，您需要设置您的 Node.js 项目。

1. 为应用程序创建一个文件夹。

   ```
   $ mkdir myproject
   $ cd myproject
   ```

1. 要初始化您的项目，请输入以下 `npm` 命令并回答安装过程中提出的问题。您可以对大多数问题使用默认值。

   ```
   $ npm init
   ```

1. 安装适用于 Node.js 的Amazon QLDB 驱动程序。
   + 使用版本 3.x

     ```
     $ npm install amazon-qldb-driver-nodejs --save
     ```
   + 使用版本 2.x

     ```
     $ npm install amazon-qldb-driver-nodejs@2.2.0 --save
     ```
   + 使用版本 1.x

     ```
     $ npm install amazon-qldb-driver-nodejs@1.0.0 --save
     ```

1. 安装驱动程序的对等依赖项。
   + 使用版本 3.x

     ```
     $ npm install @aws-sdk/client-qldb-session --save
     $ npm install ion-js --save
     $ npm install jsbi --save
     ```
   + 使用版本 2.x 或 1.x

     ```
     $ npm install aws-sdk --save
     $ npm install ion-js@4.0.0 --save
     $ npm install jsbi@3.1.1 --save
     ```

1. 创建一个名为 JavaScript、或`app.js``app.ts`为的新文件 TypeScript。

   然后，按以下步骤中逐步添加代码示例，尝试一些基本的 CRUD 操作。或者，您可以跳过本 step-by-step教程，改为运行[完整的应用程序](#driver-quickstart-nodejs.complete)。

## 第 2 步：初始化驱动程序
<a name="driver-quickstart-nodejs.step-2"></a>

初始化连接到名为 `quick-start` 的分类账的驱动程序实例。将以下代码添加到您的 `app.js` 或 `app.ts` 文件。

### 使用版本 3.x
<a name="driver-quickstart-nodejs.step-2-v3"></a>

------
#### [ JavaScript ]

```
var qldb = require('amazon-qldb-driver-nodejs');
var https = require('https');

function main() {
    const maxConcurrentTransactions = 10;
    const retryLimit = 4;

    const agentForQldb = new https.Agent({
        maxSockets: maxConcurrentTransactions
    });

    const lowLevelClientHttpOptions = {
       httpAgent: agentForQldb
    }

    const serviceConfigurationOptions = {
        region: "us-east-1"
    };

    // Use driver's default backoff function for this example (no second parameter provided to RetryConfig)
    var retryConfig = new qldb.RetryConfig(retryLimit);
    var driver = new qldb.QldbDriver("quick-start", serviceConfigurationOptions, lowlevelClientHttpOptions, maxConcurrentTransactions, retryConfig);
}

main();
```

------
#### [ TypeScript ]

```
import { Agent } from "https";
import { NodeHttpHandlerOptions } from "@aws-sdk/node-http-handler";
import { QLDBSessionClientConfig } from "@aws-sdk/client-qldb-session";
import { QldbDriver, RetryConfig } from "amazon-qldb-driver-nodejs";

function main(): void {
    const maxConcurrentTransactions: number = 10;
    const agentForQldb: Agent = new Agent({
        maxSockets: maxConcurrentTransactions
    });

    const lowLevelClientHttpOptions: NodeHttpHandlerOptions = {
      httpAgent: agentForQldb
    };

    const serviceConfigurationOptions: QLDBSessionClientConfig = {
        region: "us-east-1"
    };

    const retryLimit: number = 4;
    // Use driver's default backoff function for this example (no second parameter provided to RetryConfig)
    const retryConfig: RetryConfig = new RetryConfig(retryLimit);
    const driver: QldbDriver = new QldbDriver("quick-start", serviceConfigurationOptions, lowLevelClientHttpOptions, maxConcurrentTransactions, retryConfig);
}

if (require.main === module) {
    main();
}
```

------

**注意**  
在此代码示例中，*us-east-1*替换为您创建账本 AWS 区域 的位置。
为简单起见，本指南中的其余代码示例使用具有默认设置的驱动程序，如以下版本 1.x 示例中所述。您也可以使用您自己的驱动程序实例来代替自定义 `RetryConfig`。

### 使用版本 2.x
<a name="driver-quickstart-nodejs.step-2-v2"></a>

------
#### [ JavaScript ]

```
var qldb = require('amazon-qldb-driver-nodejs');
var https = require('https');

function main() {
    var maxConcurrentTransactions = 10;
    var retryLimit = 4;

    var agentForQldb = new https.Agent({
        keepAlive: true,
        maxSockets: maxConcurrentTransactions
    });

    var serviceConfigurationOptions = {
        region: "us-east-1",
        httpOptions: {
            agent: agentForQldb
        }
    };

    // Use driver's default backoff function for this example (no second parameter provided to RetryConfig)
    var retryConfig = new qldb.RetryConfig(retryLimit);
    var driver = new qldb.QldbDriver("quick-start", serviceConfigurationOptions, maxConcurrentTransactions, retryConfig);
}

main();
```

------
#### [ TypeScript ]

```
import { QldbDriver, RetryConfig } from "amazon-qldb-driver-nodejs";
import { ClientConfiguration } from "aws-sdk/clients/acm";
import { Agent } from "https";

function main(): void {
    const maxConcurrentTransactions: number = 10;
    const agentForQldb: Agent = new Agent({
        keepAlive: true,
        maxSockets: maxConcurrentTransactions
    });
    const serviceConfigurationOptions: ClientConfiguration = {
        region: "us-east-1",
        httpOptions: {
            agent: agentForQldb
        }
    };
    const retryLimit: number = 4;
    // Use driver's default backoff function for this example (no second parameter provided to RetryConfig)
    const retryConfig: RetryConfig = new RetryConfig(retryLimit);
    const driver: QldbDriver = new QldbDriver("quick-start", serviceConfigurationOptions, maxConcurrentTransactions, retryConfig);
}

if (require.main === module) {
    main();
}
```

------

**注意**  
在此代码示例中，*us-east-1*替换为您创建账本 AWS 区域 的位置。
版本 2.x 引入了用于初始化 `QldbDriver` 的新可选参数 `RetryConfig`。
为简单起见，本指南中的其余代码示例使用具有默认设置的驱动程序，如以下版本 1.x 示例中所述。您也可以使用您自己的驱动程序实例来代替自定义 `RetryConfig`。
此代码示例初始化一个驱动程序，该驱动程序通过设置 keep-alive 选项来重用现有连接。要了解更多信息，请参阅 [设置建议](getting-started.nodejs.md#nodejs-setup) 了解 Node.js 驱动程序。

### 使用版本 1.x
<a name="driver-quickstart-nodejs.step-2-v1"></a>

------
#### [ JavaScript ]

```
const qldb = require('amazon-qldb-driver-nodejs');

function main() {
    // Use default settings
    const driver = new qldb.QldbDriver("quick-start");
}

main();
```

------
#### [ TypeScript ]

```
import { QldbDriver } from "amazon-qldb-driver-nodejs";

function main(): void {
    // Use default settings
    const driver: QldbDriver = new QldbDriver("quick-start");
}

if (require.main === module) {
    main();
}
```

------

**注意**  
您可以设置 `AWS_REGION` 环境变量以确定区域。有关更多信息，请参阅《*适用于 JavaScript 的 AWS SDK 开发人员指南*》中的 [设置 AWS 区域](https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-region.html)。

## 第 3 步：创建表和索引
<a name="driver-quickstart-nodejs.step-3"></a>

以下代码示例显示如何运行 `CREATE TABLE` 和 `CREATE INDEX` 语句。

1. 添加以下函数，创建名为 `People` 的表。

------
#### [ JavaScript ]

   ```
   async function createTable(txn) {
       await txn.execute("CREATE TABLE People");
   }
   ```

------
#### [ TypeScript ]

   ```
   async function createTable(txn: TransactionExecutor): Promise<void> {
       await txn.execute("CREATE TABLE People");
   }
   ```

------

1. 添加以下函数，为 `People` 表中的 `firstName` 字段创建索引。[索引](ql-reference.create-index.md)是优化查询性能和帮助限制[乐观并发控制（OCC）冲突异常](concurrency.md)所必需的。

------
#### [ JavaScript ]

   ```
   async function createIndex(txn) {
       await txn.execute("CREATE INDEX ON People (firstName)");
   }
   ```

------
#### [ TypeScript ]

   ```
   async function createIndex(txn: TransactionExecutor): Promise<void> {
       await txn.execute("CREATE INDEX ON People (firstName)");
   }
   ```

------

1. 在 `main` 函数中，你先调用 `createTable`，然后调用 `createIndex`。

------
#### [ JavaScript ]

   ```
   const qldb = require('amazon-qldb-driver-nodejs');
   
   async function main() {
       // Use default settings
       const driver = new qldb.QldbDriver("quick-start");
   
       await driver.executeLambda(async (txn) => {
           console.log("Create table People");
           await createTable(txn);
           console.log("Create index on firstName");
           await createIndex(txn);
       });
   
       driver.close();
   }
   
   main();
   ```

------
#### [ TypeScript ]

   ```
   import { QldbDriver, TransactionExecutor } from "amazon-qldb-driver-nodejs";
   
   async function main(): Promise<void> {
       // Use default settings
       const driver: QldbDriver = new QldbDriver("quick-start");
   
       await driver.executeLambda(async (txn: TransactionExecutor) => {
           console.log("Create table People");
           await createTable(txn);
           console.log("Create index on firstName");
           await createIndex(txn);
       });
   
       driver.close();
   }
   
   if (require.main === module) {
       main();
   }
   ```

------

1. 运行代码以创建表和索引。

------
#### [ JavaScript ]

   ```
   $ node app.js
   ```

------
#### [ TypeScript ]

   ```
   $ tsc app.ts; node app.js
   ```

------

## 第 4 步：插入文档
<a name="driver-quickstart-nodejs.step-4"></a>

以下代码示例显示如何运行 `INSERT` 语句。QLDB 支持 [PartiQL](ql-reference.md) 查询语言（兼容 SQL）和 [Amazon Ion](ion.md) 数据格式（JSON 的超集）。

1. 添加以下函数，在 `People` 表格中插入文档。

------
#### [ JavaScript ]

   ```
   async function insertDocument(txn) {
       const person = {
           firstName: "John",
           lastName: "Doe",
           age: 42
       };
       await txn.execute("INSERT INTO People ?", person);
   }
   ```

------
#### [ TypeScript ]

   ```
   async function insertDocument(txn: TransactionExecutor): Promise<void> {
       const person: Record<string, any> = {
           firstName: "John",
           lastName: "Doe",
           age: 42
       };
       await txn.execute("INSERT INTO People ?", person);
   }
   ```

------

   此示例使用问号（`?`）作为变量占位符，将文档信息传递给语句。该 `execute` 方法同时支持 Amazon Ion 类型和 Node.js 本机类型。
**提示**  
要使用单个 [INSERT](ql-reference.insert.md) 语句插入多个文档，可以向该语句传递一个[列表](driver-working-with-ion.md#driver-ion-list)类型的参数，如下所示。  

   ```
   // people is a list
   txn.execute("INSERT INTO People ?", people);
   ```
传递 Ion 列表时，不要将变量占位符（`?`）括在双尖括号（`<<...>>`）内。在手动 PartiQL 语句中，双尖括号表示名为*bag*的无序集合。

1. 在 `main` 函数中，移除 `createTable` 和 `createIndex` 调用，然后向添加调用 `insertDocument`。

------
#### [ JavaScript ]

   ```
   const qldb = require('amazon-qldb-driver-nodejs');
   
   async function main() {
       // Use default settings
       const driver = new qldb.QldbDriver("quick-start");
   
       await driver.executeLambda(async (txn) => {
           console.log("Insert document");
           await insertDocument(txn);
       });
   
       driver.close();
   }
   
   main();
   ```

------
#### [ TypeScript ]

   ```
   import { QldbDriver, TransactionExecutor } from "amazon-qldb-driver-nodejs";
   
   async function main(): Promise<void> {
       // Use default settings
       const driver: QldbDriver = new QldbDriver("quick-start");
   
       await driver.executeLambda(async (txn: TransactionExecutor) => {
           console.log("Insert document");
           await insertDocument(txn);
       });
   
       driver.close();
   }
   
   if (require.main === module) {
       main();
   }
   ```

------

## 第 5 步：查询文档
<a name="driver-quickstart-nodejs.step-5"></a>

以下代码示例显示如何运行 `SELECT` 语句。

1. 添加以下函数，用于从 `People` 表格中查询文档。

------
#### [ JavaScript ]

   ```
   async function fetchDocuments(txn) {
       return await txn.execute("SELECT firstName, age, lastName FROM People WHERE firstName = ?", "John");
   }
   ```

------
#### [ TypeScript ]

   ```
   async function fetchDocuments(txn: TransactionExecutor): Promise<dom.Value[]> {
       return (await txn.execute("SELECT firstName, age, lastName FROM People WHERE firstName = ?", "John")).getResultList();
   }
   ```

------

1. 在 `main` 函数中，在对的调用 `fetchDocuments` 之后添加以下调用 `insertDocument`。

------
#### [ JavaScript ]

   ```
   const qldb = require('amazon-qldb-driver-nodejs');
   
   async function main() {
       // Use default settings
       const driver = new qldb.QldbDriver("quick-start");
   
       var resultList = await driver.executeLambda(async (txn) => {
           console.log("Insert document");
           await insertDocument(txn);
           console.log("Fetch document");
           var result = await fetchDocuments(txn);
           return result.getResultList();
       });
   
       // Pretty print the result list
       console.log("The result List is ", JSON.stringify(resultList, null, 2));
       driver.close();
   }
   
   main();
   ```

------
#### [ TypeScript ]

   ```
   import { QldbDriver, TransactionExecutor } from "amazon-qldb-driver-nodejs";
   import { dom } from "ion-js";
   
   async function main(): Promise<void> {
       // Use default settings
       const driver: QldbDriver = new QldbDriver("quick-start");
   
       const resultList: dom.Value[] = await driver.executeLambda(async (txn: TransactionExecutor) => {
           console.log("Insert document");
           await insertDocument(txn);
           console.log("Fetch document");
           return await fetchDocuments(txn);
       });
   
       // Pretty print the result list
       console.log("The result List is ", JSON.stringify(resultList, null, 2));
       driver.close();
   }
   
   if (require.main === module) {
       main();
   }
   ```

------

## 第 6 步：更新文档
<a name="driver-quickstart-nodejs.step-6"></a>

以下代码示例显示如何运行 `UPDATE` 语句。

1. 添加以下函数，通过修改 `lastName` 到 `"Stiles"` 来更新 `People` 表中的文档。

------
#### [ JavaScript ]

   ```
   async function updateDocuments(txn) {
       await txn.execute("UPDATE People SET lastName = ? WHERE firstName = ?", "Stiles", "John");
   }
   ```

------
#### [ TypeScript ]

   ```
   async function updateDocuments(txn: TransactionExecutor): Promise<void> {
       await txn.execute("UPDATE People SET lastName = ? WHERE firstName = ?", "Stiles", "John");
   }
   ```

------

1. 在 `main` 函数中，在对的调用 `updateDocuments` 之后添加以下调用 `fetchDocuments`。然后，再次调用 `fetchDocuments` 来查看更新的结果。

------
#### [ JavaScript ]

   ```
   const qldb = require('amazon-qldb-driver-nodejs');
   
   async function main() {
       // Use default settings
       const driver = new qldb.QldbDriver("quick-start");
   
       var resultList = await driver.executeLambda(async (txn) => {
           console.log("Insert document");
           await insertDocument(txn);
           console.log("Fetch document");
           await fetchDocuments(txn);
           console.log("Update document");
           await updateDocuments(txn);
           console.log("Fetch document after update");
           var result = await fetchDocuments(txn);
           return result.getResultList();
       });
   
       // Pretty print the result list
       console.log("The result List is ", JSON.stringify(resultList, null, 2));
       driver.close();
   }
   
   main();
   ```

------
#### [ TypeScript ]

   ```
   import { QldbDriver, TransactionExecutor } from "amazon-qldb-driver-nodejs";
   import { dom } from "ion-js";
   
   async function main(): Promise<void> {
       // Use default settings
       const driver: QldbDriver = new QldbDriver("quick-start");
   
       const resultList: dom.Value[] = await driver.executeLambda(async (txn: TransactionExecutor) => {
           console.log("Insert document");
           await insertDocument(txn);
           console.log("Fetch document");
           await fetchDocuments(txn);
           console.log("Update document");
           await updateDocuments(txn);
           console.log("Fetch document after update");
           return await fetchDocuments(txn);
       });
   
       // Pretty print the result list
       console.log("The result List is ", JSON.stringify(resultList, null, 2));
       driver.close();
   }
   
   if (require.main === module) {
       main();
   }
   ```

------

1. 运行代码以插入、查询和更新文档。

------
#### [ JavaScript ]

   ```
   $ node app.js
   ```

------
#### [ TypeScript ]

   ```
   $ tsc app.ts; node app.js
   ```

------

## 运行完整的应用程序
<a name="driver-quickstart-nodejs.complete"></a>

以下代码示例是完整版本的 `app.js` 和 `app.ts`。您还可以从头到尾运行此代码，而不必单独执行前面的步骤。此应用程序演示了对名为 `quick-start` 的分类账的一些基本的 CRUD 操作。

**注意**  
在运行此代码之前，请确保 `quick-start` 分类账中还没有名为 `People` 的活动表。

------
#### [ JavaScript ]

```
const qldb = require('amazon-qldb-driver-nodejs');

async function createTable(txn) {
    await txn.execute("CREATE TABLE People");
}

async function createIndex(txn) {
    await txn.execute("CREATE INDEX ON People (firstName)");
}

async function insertDocument(txn) {
    const person = {
        firstName: "John",
        lastName: "Doe",
        age: 42
    };
    await txn.execute("INSERT INTO People ?", person);
}

async function fetchDocuments(txn) {
    return await txn.execute("SELECT firstName, age, lastName FROM People WHERE firstName = ?", "John");
}

async function updateDocuments(txn) {
    await txn.execute("UPDATE People SET lastName = ? WHERE firstName = ?", "Stiles", "John");
}

async function main() {
    // Use default settings
    const driver = new qldb.QldbDriver("quick-start");

    var resultList = await driver.executeLambda(async (txn) => {
        console.log("Create table People");
        await createTable(txn);
        console.log("Create index on firstName");
        await createIndex(txn);
        console.log("Insert document");
        await insertDocument(txn);
        console.log("Fetch document");
        await fetchDocuments(txn);
        console.log("Update document");
        await updateDocuments(txn);
        console.log("Fetch document after update");
        var result = await fetchDocuments(txn);
        return result.getResultList();
    });

    // Pretty print the result list
    console.log("The result List is ", JSON.stringify(resultList, null, 2));
    driver.close();
}

main();
```

------
#### [ TypeScript ]

```
import { QldbDriver, TransactionExecutor } from "amazon-qldb-driver-nodejs";
import { dom } from "ion-js";

async function createTable(txn: TransactionExecutor): Promise<void> {
    await txn.execute("CREATE TABLE People");
}

async function createIndex(txn: TransactionExecutor): Promise<void> {
    await txn.execute("CREATE INDEX ON People (firstName)");
}

async function insertDocument(txn: TransactionExecutor): Promise<void> {
    const person: Record<string, any> = {
        firstName: "John",
        lastName: "Doe",
        age: 42
    };
    await txn.execute("INSERT INTO People ?", person);
}

async function fetchDocuments(txn: TransactionExecutor): Promise<dom.Value[]> {
    return (await txn.execute("SELECT firstName, age, lastName FROM People WHERE firstName = ?", "John")).getResultList();
}

async function updateDocuments(txn: TransactionExecutor): Promise<void> {
    await txn.execute("UPDATE People SET lastName = ? WHERE firstName = ?", "Stiles", "John");
};

async function main(): Promise<void> {
    // Use default settings
    const driver: QldbDriver = new QldbDriver("quick-start");

    const resultList: dom.Value[] = await driver.executeLambda(async (txn: TransactionExecutor) => {
        console.log("Create table People");
        await createTable(txn);
        console.log("Create index on firstName");
        await createIndex(txn);
        console.log("Insert document");
        await insertDocument(txn);
        console.log("Fetch document");
        await fetchDocuments(txn);
        console.log("Update document");
        await updateDocuments(txn);
        console.log("Fetch document after update");
        return await fetchDocuments(txn);
    });

    // Pretty print the result list
    console.log("The result List is ", JSON.stringify(resultList, null, 2));
    driver.close();
}

if (require.main === module) {
    main();
}
```

------

要运行完整的应用程序，请输入以下命令。

------
#### [ JavaScript ]

```
$ node app.js
```

------
#### [ TypeScript ]

```
$ tsc app.ts; node app.js
```

------