Node.js 的亞馬遜 QLDB 驅動程序-食譜參考 - Amazon Quantum Ledger Database (Amazon QLDB)

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

Node.js 的亞馬遜 QLDB 驅動程序-食譜參考

本參考指南顯示適用於 Node.js 的亞馬遜 QLDB 驅動程式的常見使用案例。它提供 JavaScript 的程式 TypeScript 碼範例會示範如何使用驅動程式來執行基本的建立、讀取、更新及刪除 (CRUD) 操作。它還包括用於處理 Amazon Ion 資料的程式碼範例。此外,本指南還重點介紹了使交易冪等和實施唯一性約束的最佳實踐。

匯入驅動程式

下列程式碼範例會匯入驅動程式。

JavaScript
var qldb = require('amazon-qldb-driver-nodejs'); var ionjs = require('ion-js');
TypeScript
import { QldbDriver, TransactionExecutor } from "amazon-qldb-driver-nodejs"; import { dom, dumpBinary, load } from "ion-js";
注意

此範例也會匯入 Amazon Ion 套件 (ion-js)。在此參考中執行某些資料作業時,您需要此套件來處理 Ion 資料。如需進一步了解,請參閱 使用 Amazon Ion

實例化驅動程式

下列程式碼範例會建立使用預設設定連線至指定分類帳名稱的驅動程式執行環境。

JavaScript
const qldbDriver = new qldb.QldbDriver("vehicle-registration");
TypeScript
const qldbDriver: QldbDriver = new QldbDriver("vehicle-registration");

CRUD 操作

QLDB 運行建立、讀取、更新及刪除 (CRUD) 操作。

警告

根據最佳實務,寫入交易必須使用嚴格的冪等。

使交易冪等

我們建議您將寫入事務設為冪等,以避免在重試的情況下出現任何意外的副作用。如果事務可以運行多次並每次產生相同的結果,則事務是冪等的。

例如,假設將文件插入名為的資料表中的交易Person。事務應該首先檢查該文檔是否已經存在於表中。如果沒有此檢查,表格最終可能會出現重複的文件。

假設 QLDB 成功地在服務器端提交事務,但在等待響應的客戶端超時。如果事務不是冪等的,則在重試的情況下,可以多次插入相同的文檔。

使用索引來避免完整表格掃描

我們也建議您在索引欄位或文件 ID 上使用相等運算子來執行具有述WHERE詞子句的陳述式;例如,WHERE indexedField = 123WHERE indexedField IN (456, 789)。如果沒有此索引查找,QLDB 需要進行表掃描,這可能會導致交易逾時或樂觀並發控制(OCC)衝突。

如需的詳細資訊,請參閱Amazon QLLDB 並行模型

隱含建立的交易

QldbDriver.executelambda 方法接受接收的TransactionExecutor執行個體 (可用來執行陳述式) 的 Lambda 函數。TransactionExecutor封裝隱含建立之交易的執行個體。

您可以使用交易執行程式的執行方法,在 lambda 函數中執行陳述式。當 lambda 函數返回時,驅動程序隱式地提交交易。

注意

此方execute法同時支援亞馬遜離子類型和 Node.js 原生類型。如果您將 Node.js 原生類型作為引數傳遞給execute,驅動程式會使用ion-js套件將其轉換為 Ion 類型 (前提是支援指定 Node.js 資料類型的轉換)。有關支持的數據類型和轉換規則,請參閱 Ion JavaScript DOM 自述文件

下列各節說明如何執行基本 CRUD 作業、指定自訂重試邏輯,以及實作唯一性限制。

建立資料表

JavaScript
(async function() { await qldbDriver.executeLambda(async (txn) => { await txn.execute("CREATE TABLE Person"); }); })();
TypeScript
(async function(): Promise<void> { await qldbDriver.executeLambda(async (txn: TransactionExecutor) => { await txn.execute('CREATE TABLE Person'); }); }());

建立索引

JavaScript
(async function() { await qldbDriver.executeLambda(async (txn) => { await txn.execute("CREATE INDEX ON Person (GovId)"); }); })();
TypeScript
(async function(): Promise<void> { await qldbDriver.executeLambda(async (txn: TransactionExecutor) => { await txn.execute('CREATE INDEX ON Person (GovId)'); }); }());

閱讀文件

JavaScript
(async function() { // Assumes that Person table has documents as follows: // { "GovId": "TOYENC486FH", "FirstName": "Brent" } await qldbDriver.executeLambda(async (txn) => { const results = (await txn.execute("SELECT * FROM Person WHERE GovId = 'TOYENC486FH'")).getResultList(); for (let result of results) { console.log(result.get('GovId')); // prints [String: 'TOYENC486FH'] console.log(result.get('FirstName')); // prints [String: 'Brent'] } }); }());
TypeScript
(async function(): Promise<void> { // Assumes that Person table has documents as follows: // { "GovId": "TOYENC486FH", "FirstName": "Brent" } await qldbDriver.executeLambda(async (txn: TransactionExecutor) => { const results: dom.Value[] = (await txn.execute("SELECT * FROM Person WHERE GovId = 'TOYENC486FH'")).getResultList(); for (let result of results) { console.log(result.get('GovId')); // prints [String: 'TOYENC486FH'] console.log(result.get('FirstName')); // prints [String: 'Brent'] } }); }());

使用查詢參數

下列程式碼範例會使用原生型別查詢參數。

JavaScript
(async function() { // Assumes that Person table has documents as follows: // { "GovId": "TOYENC486FH", "FirstName": "Brent" } await qldbDriver.executeLambda(async (txn) => { const results = (await txn.execute('SELECT * FROM Person WHERE GovId = ?', 'TOYENC486FH')).getResultList(); for (let result of results) { console.log(result.get('GovId')); // prints [String: 'TOYENC486FH'] console.log(result.get('FirstName')); // prints [String: 'Brent'] } }); }());
TypeScript
(async function(): Promise<void> { // Assumes that Person table has documents as follows: // { "GovId": "TOYENC486FH", "FirstName": "Brent" } await qldbDriver.executeLambda(async (txn: TransactionExecutor) => { const results: dom.Value[] = (await txn.execute('SELECT * FROM Person WHERE GovId = ?', 'TOYENC486FH')).getResultList(); for (let result of results) { console.log(result.get('GovId')); // prints [String: 'TOYENC486FH'] console.log(result.get('FirstName')); // prints [String: 'Brent'] } }); }());

下列程式碼範例會使用 Ion 型別查詢參數。

JavaScript
(async function() { await qldbDriver.executeLambda(async (txn) => { const govId = ionjs.load("TOYENC486FH"); const results = (await txn.execute('SELECT * FROM Person WHERE GovId = ?', govId)).getResultList(); for (let result of results) { console.log(result.get('GovId')); // prints [String: 'TOYENC486FH'] console.log(result.get('FirstName')); // prints [String: 'Brent'] } }); }());
TypeScript
(async function(): Promise<void> { await qldbDriver.executeLambda(async (txn: TransactionExecutor) => { const govId: dom.Value = load("TOYENC486FH"); const results: dom.Value[] = (await txn.execute('SELECT * FROM Person WHERE GovId = ?', govId)).getResultList(); for (let result of results) { console.log(result.get('GovId')); // prints [String: 'TOYENC486FH'] console.log(result.get('FirstName')); // prints [String: 'Brent'] } }); }());

下列程式碼範例會使用多個查詢參數。

JavaScript
(async function() { await qldbDriver.executeLambda(async (txn) => { const results = (await txn.execute('SELECT * FROM Person WHERE GovId = ? AND FirstName = ?', 'TOYENC486FH', 'Brent')).getResultList(); for (let result of results) { console.log(result.get('GovId')); // prints [String: 'TOYENC486FH'] console.log(result.get('FirstName')); // prints [String: 'Brent'] } }); }());
TypeScript
(async function(): Promise<void> { await qldbDriver.executeLambda(async (txn: TransactionExecutor) => { const results: dom.Value[] = (await txn.execute('SELECT * FROM Person WHERE GovId = ? AND FirstName = ?', 'TOYENC486FH', 'Brent')).getResultList(); for (let result of results) { console.log(result.get('GovId')); // prints [String: 'TOYENC486FH'] console.log(result.get('FirstName')); // prints [String: 'Brent'] } }); }());

下列程式碼範例使用查詢參數清單。

JavaScript
(async function() { await qldbDriver.executeLambda(async (txn) => { const govIds = ['TOYENC486FH','LOGANB486CG','LEWISR261LL']; /* Assumes that Person table has documents as follows: { "GovId": "TOYENC486FH", "FirstName": "Brent" } { "GovId": "LOGANB486CG", "FirstName": "Brent" } { "GovId": "LEWISR261LL", "FirstName": "Raul" } */ const results = (await txn.execute('SELECT * FROM Person WHERE GovId IN (?,?,?)', ...govIds)).getResultList(); for (let result of results) { console.log(result.get('GovId')); console.log(result.get('FirstName')); /* prints: [String: 'TOYENC486FH'] [String: 'Brent'] [String: 'LOGANB486CG'] [String: 'Brent'] [String: 'LEWISR261LL'] [String: 'Raul'] */ } }); }());
TypeScript
(async function(): Promise<void> { await qldbDriver.executeLambda(async (txn: TransactionExecutor) => { const govIds: string[] = ['TOYENC486FH','LOGANB486CG','LEWISR261LL']; /* Assumes that Person table has documents as follows: { "GovId": "TOYENC486FH", "FirstName": "Brent" } { "GovId": "LOGANB486CG", "FirstName": "Brent" } { "GovId": "LEWISR261LL", "FirstName": "Raul" } */ const results: dom.Value[] = (await txn.execute('SELECT * FROM Person WHERE GovId IN (?,?,?)', ...govIds)).getResultList(); for (let result of results) { console.log(result.get('GovId')); console.log(result.get('FirstName')); /* prints: [String: 'TOYENC486FH'] [String: 'Brent'] [String: 'LOGANB486CG'] [String: 'Brent'] [String: 'LEWISR261LL'] [String: 'Raul'] */ } }); }());
注意

當您在沒有索引查閱的情況下執行查詢時,會叫用完整資料表掃描。在此範例中,我們建議在GovId欄位上建立索引以最佳化效能。如果沒有開啟索引GovId,查詢可能會有更多延遲,也可能導致 OCC 衝突例外狀況或交易逾時。

插入文件

下列程式碼範例會插入原生資料類型。

JavaScript
(async function() { await qldbDriver.executeLambda(async (txn) => { // Check if doc with GovId:TOYENC486FH exists // This is critical to make this transaction idempotent const results = (await txn.execute('SELECT * FROM Person WHERE GovId = ?', 'TOYENC486FH')).getResultList(); // Insert the document after ensuring it doesn't already exist if (results.length == 0) { const doc = { 'FirstName': 'Brent', 'GovId': 'TOYENC486FH', }; await txn.execute('INSERT INTO Person ?', doc); } }); }());
TypeScript
(async function(): Promise<void> { await qldbDriver.executeLambda(async (txn: TransactionExecutor) => { // Check if doc with GovId:TOYENC486FH exists // This is critical to make this transaction idempotent const results: dom.Value[] = (await txn.execute('SELECT * FROM Person WHERE GovId = ?', 'TOYENC486FH')).getResultList(); // Insert the document after ensuring it doesn't already exist if (results.length == 0) { const doc: Record<string, string> = { 'FirstName': 'Brent', 'GovId': 'TOYENC486FH', }; await txn.execute('INSERT INTO Person ?', doc); } }); }());

下列程式碼範例會插入 Ion 資料型別。

JavaScript
(async function() { await qldbDriver.executeLambda(async (txn) => { // Check if doc with GovId:TOYENC486FH exists // This is critical to make this transaction idempotent const results = (await txn.execute('SELECT * FROM Person WHERE GovId = ?', 'TOYENC486FH')).getResultList(); // Insert the document after ensuring it doesn't already exist if (results.length == 0) { const doc = { 'FirstName': 'Brent', 'GovId': 'TOYENC486FH', }; // Create a sample Ion doc const ionDoc = ionjs.load(ionjs.dumpBinary(doc)); await txn.execute('INSERT INTO Person ?', ionDoc); } }); }());
TypeScript
(async function(): Promise<void> { await qldbDriver.executeLambda(async (txn: TransactionExecutor) => { // Check if doc with GovId:TOYENC486FH exists // This is critical to make this transaction idempotent const results: dom.Value[] = (await txn.execute('SELECT * FROM Person WHERE GovId = ?', 'TOYENC486FH')).getResultList(); // Insert the document after ensuring it doesn't already exist if (results.length == 0) { const doc: Record<string, string> = { 'FirstName': 'Brent', 'GovId': 'TOYENC486FH', }; // Create a sample Ion doc const ionDoc: dom.Value = load(dumpBinary(doc)); await txn.execute('INSERT INTO Person ?', ionDoc); } }); }());

此事務將一個文檔插入到Person表中。在插入之前,它會先檢查文件是否已存在於表格中。這個檢查使事務本質上是冪等的。即使您多次運行此事務,也不會造成任何意外的副作用。

注意

在此範例中,我們建議在GovId欄位上建立索引以最佳化效能。如果沒有開啟索引GovId,陳述式可能會有更多延遲,也可能導致 OCC 衝突例外狀況或交易逾時。

在一個語句中插入多個文檔

要通過使用單個INSERT語句插入多個文檔,你可以通過類型列表的參數到語句如下。

// people is a list txn.execute("INSERT INTO People ?", people);

傳遞清單時,您不會將變數預留位置 (?<<...>>) 括在雙尖括號 () 中。在手動 PartiQL 陳述式中,雙角括號表示稱為袋子的無序集合。

更新文件

下列程式碼範例會使用原生資料類型。

JavaScript
(async function() { await qldbDriver.executeLambda(async (txn) => { await txn.execute('UPDATE Person SET FirstName = ? WHERE GovId = ?', 'John', 'TOYENC486FH'); }); }());
TypeScript
(async function(): Promise<void> { await qldbDriver.executeLambda(async (txn: TransactionExecutor) => { await txn.execute('UPDATE Person SET FirstName = ? WHERE GovId = ?', 'John', 'TOYENC486FH'); }); }());

下列程式碼範例會使用 Ion 資料型別。

JavaScript
(async function() { await qldbDriver.executeLambda(async (txn) => { const firstName = ionjs.load("John"); const govId = ionjs.load("TOYENC486FH"); await txn.execute('UPDATE Person SET FirstName = ? WHERE GovId = ?', firstName, govId); }); }());
TypeScript
(async function(): Promise<void> { await qldbDriver.executeLambda(async (txn: TransactionExecutor) => { const firstName: dom.Value = load("John"); const govId: dom.Value = load("TOYENC486FH"); await txn.execute('UPDATE Person SET FirstName = ? WHERE GovId = ?', firstName, govId); }); }());
注意

在此範例中,我們建議在GovId欄位上建立索引以最佳化效能。如果沒有開啟索引GovId,陳述式可能會有更多延遲,也可能導致 OCC 衝突例外狀況或交易逾時。

刪除文件

下列程式碼範例會使用原生資料類型。

JavaScript
(async function() { await qldbDriver.executeLambda(async (txn) => { await txn.execute('DELETE FROM Person WHERE GovId = ?', 'TOYENC486FH'); }); }());
TypeScript
(async function(): Promise<void> { await qldbDriver.executeLambda(async (txn: TransactionExecutor) => { await txn.execute('DELETE FROM Person WHERE GovId = ?', 'TOYENC486FH'); }); }());

下列程式碼範例會使用 Ion 資料型別。

JavaScript
(async function() { await qldbDriver.executeLambda(async (txn) => { const govId = ionjs.load("TOYENC486FH"); await txn.execute('DELETE FROM Person WHERE GovId = ?', govId); }); }());
TypeScript
(async function(): Promise<void> { await qldbDriver.executeLambda(async (txn: TransactionExecutor) => { const govId: dom.Value = load("TOYENC486FH"); await txn.execute('DELETE FROM Person WHERE GovId = ?', govId); }); }());
注意

在此範例中,我們建議在GovId欄位上建立索引以最佳化效能。如果沒有開啟索引GovId,陳述式可能會有更多延遲,也可能導致 OCC 衝突例外狀況或交易逾時。

在交易中執行多個陳述式

TypeScript
// This code snippet is intentionally trivial. In reality you wouldn't do this because you'd // set your UPDATE to filter on vin and insured, and check if you updated something or not. async function insureCar(driver: QldbDriver, vin: string): Promise<boolean> { return await driver.executeLambda(async (txn: TransactionExecutor) => { const results: dom.Value[] = (await txn.execute( "SELECT insured FROM Vehicles WHERE vin = ? AND insured = FALSE", vin)).getResultList(); if (results.length > 0) { await txn.execute( "UPDATE Vehicles SET insured = TRUE WHERE vin = ?", vin); return true; } return false; }); };

重試邏輯

驅動程式的executeLambda方法具有內建的重試機制,可在發生可重試的例外狀況 (例如逾時或 OCC 衝突) 時重試交易。重試嘗試嘗試次數的上限和輪詢策略是可設定的。

預設重試限制為4,且預設的輪詢策略defaultBackoffFunction10毫秒為基礎。您可以使用的執行個體來設定每個驅動程式執行個體以及每個交易的重試組態RetryConfig

下列程式碼範例會指定具有自訂重試限制的重試邏輯,以及驅動程式執行個體的自訂輪詢策略。

JavaScript
var qldb = require('amazon-qldb-driver-nodejs'); // Configuring retry limit to 2 const retryConfig = new qldb.RetryConfig(2); const qldbDriver = new qldb.QldbDriver("test-ledger", undefined, undefined, retryConfig); // Configuring a custom backoff which increases delay by 1s for each attempt. const customBackoff = (retryAttempt, error, transactionId) => { return 1000 * retryAttempt; }; const retryConfigCustomBackoff = new qldb.RetryConfig(2, customBackoff); const qldbDriverCustomBackoff = new qldb.QldbDriver("test-ledger", undefined, undefined, retryConfigCustomBackoff);
TypeScript
import { BackoffFunction, QldbDriver, RetryConfig } from "amazon-qldb-driver-nodejs" // Configuring retry limit to 2 const retryConfig: RetryConfig = new RetryConfig(2); const qldbDriver: QldbDriver = new QldbDriver("test-ledger", undefined, undefined, retryConfig); // Configuring a custom backoff which increases delay by 1s for each attempt. const customBackoff: BackoffFunction = (retryAttempt: number, error: Error, transactionId: string) => { return 1000 * retryAttempt; }; const retryConfigCustomBackoff: RetryConfig = new RetryConfig(2, customBackoff); const qldbDriverCustomBackoff: QldbDriver = new QldbDriver("test-ledger", undefined, undefined, retryConfigCustomBackoff);

下列程式碼範例會指定具有自訂重試限制的重試邏輯,以及針對特定 lambda 執行的自訂輪詢策略。此組態executeLambda會覆寫為驅動程式執行個體設定的重試邏輯。

JavaScript
var qldb = require('amazon-qldb-driver-nodejs'); // Configuring retry limit to 2 const retryConfig1 = new qldb.RetryConfig(2); const qldbDriver = new qldb.QldbDriver("test-ledger", undefined, undefined, retryConfig1); // Configuring a custom backoff which increases delay by 1s for each attempt. const customBackoff = (retryAttempt, error, transactionId) => { return 1000 * retryAttempt; }; const retryConfig2 = new qldb.RetryConfig(2, customBackoff); // The config `retryConfig1` will be overridden by `retryConfig2` (async function() { await qldbDriver.executeLambda(async (txn) => { await txn.execute('CREATE TABLE Person'); }, retryConfig2); }());
TypeScript
import { BackoffFunction, QldbDriver, RetryConfig, TransactionExecutor } from "amazon-qldb-driver-nodejs" // Configuring retry limit to 2 const retryConfig1: RetryConfig = new RetryConfig(2); const qldbDriver: QldbDriver = new QldbDriver("test-ledger", undefined, undefined, retryConfig1); // Configuring a custom backoff which increases delay by 1s for each attempt. const customBackoff: BackoffFunction = (retryAttempt: number, error: Error, transactionId: string) => { return 1000 * retryAttempt; }; const retryConfig2: RetryConfig = new RetryConfig(2, customBackoff); // The config `retryConfig1` will be overridden by `retryConfig2` (async function(): Promise<void> { await qldbDriver.executeLambda(async (txn: TransactionExecutor) => { await txn.execute('CREATE TABLE Person'); }, retryConfig2); }());

實施唯一性限制

QLDB 不支援唯一索引,但您可以在應用程式中實作此行為。

假設您要在Person表中的GovId字段上實現唯一性約束。要執行此操作,您可以編寫執行下列操作的交易:

  1. 斷言該表沒有具有指定的現有文檔GovId

  2. 插入文檔,如果斷言通過。

如果競爭交易同時通過斷言,則只有其中一個交易將成功提交。另一個交易將會失敗,並出現 OCC 衝突例外狀況。

下列程式碼範例示範例示範如何實現此唯一性限制邏輯。

JavaScript
const govId = 'TOYENC486FH'; const document = { 'FirstName': 'Brent', 'GovId': 'TOYENC486FH', }; (async function() { await qldbDriver.executeLambda(async (txn) => { // Check if doc with GovId = govId exists const results = (await txn.execute('SELECT * FROM Person WHERE GovId = ?', govId)).getResultList(); // Insert the document after ensuring it doesn't already exist if (results.length == 0) { await txn.execute('INSERT INTO Person ?', document); } }); })();
TypeScript
const govId: string = 'TOYENC486FH'; const document: Record<string, string> = { 'FirstName': 'Brent', 'GovId': 'TOYENC486FH', }; (async function(): Promise<void> { await qldbDriver.executeLambda(async (txn: TransactionExecutor) => { // Check if doc with GovId = govId exists const results: dom.Value[] = (await txn.execute('SELECT * FROM Person WHERE GovId = ?', govId)).getResultList(); // Insert the document after ensuring it doesn't already exist if (results.length == 0) { await txn.execute('INSERT INTO Person ?', document); } }); })();
注意

在此範例中,我們建議在GovId欄位上建立索引以最佳化效能。如果沒有開啟索引GovId,陳述式可能會有更多延遲,也可能導致 OCC 衝突例外狀況或交易逾時。

使用 Amazon Ion

下列幾節說明如何使用 Amazon Ion 模組來處理 Ion 資料。

匯入離子模組

JavaScript
var ionjs = require('ion-js');
TypeScript
import { dom, dumpBinary, dumpText, load } from "ion-js";

建立 Ion 類型

下列程式碼範例會從 Ion 文字建立 Ion 物件。

JavaScript
const ionText = '{GovId: "TOYENC486FH", FirstName: "Brent"}'; const ionObj = ionjs.load(ionText); console.log(ionObj.get('GovId')); // prints [String: 'TOYENC486FH'] console.log(ionObj.get('FirstName')); // prints [String: 'Brent']
TypeScript
const ionText: string = '{GovId: "TOYENC486FH", FirstName: "Brent"}'; const ionObj: dom.Value = load(ionText); console.log(ionObj.get('GovId')); // prints [String: 'TOYENC486FH'] console.log(ionObj.get('FirstName')); // prints [String: 'Brent']

下列程式碼範例會使用 Node.js 字典建立 Ion 物件。

JavaScript
const aDict = { 'GovId': 'TOYENC486FH', 'FirstName': 'Brent' }; const ionObj = ionjs.load(ionjs.dumpBinary(aDict)); console.log(ionObj.get('GovId')); // prints [String: 'TOYENC486FH'] console.log(ionObj.get('FirstName')); // prints [String: 'Brent']
TypeScript
const aDict: Record<string, string> = { 'GovId': 'TOYENC486FH', 'FirstName': 'Brent' }; const ionObj: dom.Value = load(dumpBinary(aDict)); console.log(ionObj.get('GovId')); // prints [String: 'TOYENC486FH'] console.log(ionObj.get('FirstName')); // prints [String: 'Brent']

獲取離子二進制轉儲

JavaScript
// ionObj is an Ion struct console.log(ionjs.dumpBinary(ionObj).toString()); // prints 224,1,0,234,238,151,129,131,222,147,135,190,144,133,71,111,118,73,100,137,70,105,114,115,116,78,97,109,101,222,148,138,139,84,79,89,69,78,67,52,56,54,70,72,139,133,66,114,101,110,116
TypeScript
// ionObj is an Ion struct console.log(dumpBinary(ionObj).toString()); // prints 224,1,0,234,238,151,129,131,222,147,135,190,144,133,71,111,118,73,100,137,70,105,114,115,116,78,97,109,101,222,148,138,139,84,79,89,69,78,67,52,56,54,70,72,139,133,66,114,101,110,116

獲取離子文本轉儲

JavaScript
// ionObj is an Ion struct console.log(ionjs.dumpText(ionObj)); // prints {GovId:"TOYENC486FH",FirstName:"Brent"}
TypeScript
// ionObj is an Ion struct console.log(dumpText(ionObj)); // prints {GovId:"TOYENC486FH",FirstName:"Brent"}

如需 Ion 的詳細資訊,請參閱上的 Amazon Ion 文件 GitHub。如需在 QLDB 中使用 Ion 的更多程式碼範例,請參閱在亞馬遜 QLDB 中使用亞馬遜離子數據類型