

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

# Amazon QLDB-Treiber für Node.js — Kochbuch-Referenz
<a name="driver-cookbook-nodejs"></a>

**Wichtig**  
Hinweis zum Ende des Supports: Bestandskunden können Amazon QLDB bis zum Ende des Supports am 31.07.2025 nutzen. Weitere Informationen finden Sie unter [Migrieren eines Amazon QLDB-Ledgers zu Amazon](https://aws.amazon.com/blogs/database/migrate-an-amazon-qldb-ledger-to-amazon-aurora-postgresql/) Aurora PostgreSQL.

Dieses Referenzhandbuch zeigt allgemeine Anwendungsfälle des Amazon QLDB-Treibers für Node.js. Es enthält JavaScript TypeScript Codebeispiele, die zeigen, wie der Treiber verwendet wird, um grundlegende *Erstellungs-, Lese-, Aktualisierungs- und Löschvorgänge* (CRUD) auszuführen. Es enthält auch Codebeispiele für die Verarbeitung von Amazon Ion-Daten. Darüber hinaus werden in diesem Leitfaden bewährte Verfahren zur idempotenten Gestaltung von Transaktionen und zur Implementierung von Eindeutigkeitsbeschränkungen beschrieben.

**Contents**
+ [Den Treiber importieren](#cookbook-nodejs.importing)
+ [Der Treiber wird instanziiert](#cookbook-nodejs.instantiating)
+ [CRUD-Operationen](#cookbook-nodejs.crud)
  + [Erstellen von Tabellen](#cookbook-nodejs.crud.creating-tables)
  + [Erstellen von Indizes](#cookbook-nodejs.crud.creating-indexes)
  + [Dokumente lesen](#cookbook-nodejs.crud.reading)
    + [Verwenden von Abfrageparametern](#cookbook-nodejs.reading-using-params)
  + [Dokumente werden eingefügt](#cookbook-nodejs.crud.inserting)
    + [Einfügen mehrerer Dokumente in eine Anweisung](#cookbook-nodejs.crud.inserting.multiple)
  + [Dokumente werden aktualisiert](#cookbook-nodejs.crud.updating)
  + [Dokumente löschen](#cookbook-nodejs.crud.deleting)
  + [Ausführung mehrerer Anweisungen in einer Transaktion](#cookbook-nodejs.crud.multi-statement)
  + [Logik für Wiederholversuche](#cookbook-nodejs.crud.retry-logic)
  + [Implementierung von Eindeutigkeitsbeschränkungen](#cookbook-nodejs.crud.uniqueness-constraints)
+ [Arbeiten mit Amazon Ion](#cookbook-nodejs.ion)
  + [Das Ion-Modul importieren](#cookbook-nodejs.ion.import)
  + [Ion-Typen erstellen](#cookbook-nodejs.ion.creating-types)
  + [Einen Ion-Binär-Dump abrufen](#cookbook-nodejs.ion.getting-binary)
  + [Einen Ion-Textdump abrufen](#cookbook-nodejs.ion.getting-text)

## Den Treiber importieren
<a name="cookbook-nodejs.importing"></a>

Das folgende Codebeispiel importiert den Treiber.

------
#### [ 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";
```

------

**Anmerkung**  
In diesem Beispiel wird auch das Amazon Ion-Paket (`ion-js`) importiert. Sie benötigen dieses Paket, um Ion-Daten zu verarbeiten, wenn Sie einige Datenoperationen in dieser Referenz ausführen. Weitere Informationen hierzu finden Sie unter [Arbeiten mit Amazon Ion](#cookbook-nodejs.ion).

## Der Treiber wird instanziiert
<a name="cookbook-nodejs.instantiating"></a>

Im folgenden Codebeispiel wird eine Instanz des Treibers erstellt, die mithilfe der Standardeinstellungen eine Verbindung zu einem angegebenen Ledger-Namen herstellt.

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

```
const qldbDriver = new qldb.QldbDriver("vehicle-registration");
```

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

```
const qldbDriver: QldbDriver = new QldbDriver("vehicle-registration");
```

------

## CRUD-Operationen
<a name="cookbook-nodejs.crud"></a>

QLDB führt *Erstellungs-, Lese-, Aktualisierungs- und Löschvorgänge* (CRUD) als Teil einer Transaktion aus.

**Warnung**  
Als bewährte Methode sollten Sie Ihre Schreibtransaktionen strikt idempotent gestalten.

**Transaktionen idempotent machen**

Wir empfehlen, Schreibtransaktionen idempotent zu machen, um unerwartete Nebenwirkungen bei Wiederholungsversuchen zu vermeiden. Eine Transaktion ist *idempotent*, wenn sie mehrfach ausgeführt werden kann und jedes Mal identische Ergebnisse liefert.

Stellen Sie sich zum Beispiel eine Transaktion vor, die ein Dokument in eine Tabelle mit dem Namen einfügt. `Person` Bei der Transaktion sollte zunächst geprüft werden, ob das Dokument bereits in der Tabelle vorhanden ist. Ohne diese Prüfung könnte die Tabelle doppelte Dokumente enthalten.

Nehmen wir an, dass QLDB die Transaktion auf der Serverseite erfolgreich festschreibt, der Client jedoch während des Wartens auf eine Antwort eine Zeitüberschreitung ausführt. Wenn die Transaktion nicht idempotent ist, könnte dasselbe Dokument bei einem erneuten Versuch mehrmals eingefügt werden.

**Verwendung von Indizes zur Vermeidung vollständiger Tabellenscans**

Es wird außerdem empfohlen, Anweisungen mit einer `WHERE` Prädikatklausel unter Verwendung eines *Gleichheitsoperators* für ein indiziertes Feld oder eine Dokument-ID auszuführen, z. B. oder. `WHERE indexedField = 123` `WHERE indexedField IN (456, 789)` Ohne diese indizierte Suche muss QLDB einen Tabellenscan durchführen, was zu Transaktions-Timeouts oder Konflikten mit *optimistischer Parallelitätskontrolle* (OCC) führen kann.

Weitere Informationen zu OCC finden Sie unter [Amazon QLDB-Parallelitätsmodell](concurrency.md).

**Implizit erstellte Transaktionen**

Die [QldbDriver.executeLambda-Methode](https://amazon-qldb-docs.s3.amazonaws.com/drivers/nodejs/2.2.0/classes/_src_qldbdriver_.qldbdriver.html#executelambda) akzeptiert eine Lambda-Funktion, die eine Instanz von empfängt, mit der [TransactionExecutor](https://amazon-qldb-docs.s3.amazonaws.com/drivers/nodejs/2.2.0/classes/_src_transactionexecutor_.transactionexecutor.html)Sie Anweisungen ausführen können. Die Instanz von umschließt eine implizit erstellte Transaktion. `TransactionExecutor`

Sie können Anweisungen innerhalb der Lambda-Funktion ausführen, indem Sie die [Execute-Methode des Transaktions-Executors](https://amazon-qldb-docs.s3.amazonaws.com/drivers/nodejs/2.2.0/classes/_src_transactionexecutor_.transactionexecutor.html#execute) verwenden. Der Treiber schreibt die Transaktion implizit fest, wenn die Lambda-Funktion zurückkehrt.

**Anmerkung**  
Die `execute` Methode unterstützt sowohl Amazon Ion-Typen als auch native Typen von Node.js. Wenn Sie einen systemeigenen Typ Node.js als Argument an übergeben`execute`, konvertiert der Treiber ihn mithilfe des `ion-js` Pakets in einen Ion-Typ (vorausgesetzt, dass die Konvertierung für den angegebenen Node.js -Datentyp unterstützt wird). Informationen zu unterstützten Datentypen und Konvertierungsregeln finden Sie in der JavaScript [Ion-DOM-README-Datei](https://github.com/amzn/ion-js/blob/master/src/dom/README.md).

In den folgenden Abschnitten wird gezeigt, wie grundlegende CRUD-Operationen ausgeführt, eine benutzerdefinierte Wiederholungslogik angegeben und Eindeutigkeitsbeschränkungen implementiert werden.

**Contents**
+ [Erstellen von Tabellen](#cookbook-nodejs.crud.creating-tables)
+ [Erstellen von Indizes](#cookbook-nodejs.crud.creating-indexes)
+ [Dokumente lesen](#cookbook-nodejs.crud.reading)
  + [Verwenden von Abfrageparametern](#cookbook-nodejs.reading-using-params)
+ [Dokumente werden eingefügt](#cookbook-nodejs.crud.inserting)
  + [Einfügen mehrerer Dokumente in eine Anweisung](#cookbook-nodejs.crud.inserting.multiple)
+ [Dokumente werden aktualisiert](#cookbook-nodejs.crud.updating)
+ [Dokumente löschen](#cookbook-nodejs.crud.deleting)
+ [Ausführung mehrerer Anweisungen in einer Transaktion](#cookbook-nodejs.crud.multi-statement)
+ [Logik für Wiederholversuche](#cookbook-nodejs.crud.retry-logic)
+ [Implementierung von Eindeutigkeitsbeschränkungen](#cookbook-nodejs.crud.uniqueness-constraints)

### Erstellen von Tabellen
<a name="cookbook-nodejs.crud.creating-tables"></a>

------
#### [ 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');
    });
}());
```

------

### Erstellen von Indizes
<a name="cookbook-nodejs.crud.creating-indexes"></a>

------
#### [ 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)');
    });
}());
```

------

### Dokumente lesen
<a name="cookbook-nodejs.crud.reading"></a>

------
#### [ 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']
        }
    });
}());
```

------

#### Verwenden von Abfrageparametern
<a name="cookbook-nodejs.reading-using-params"></a>

Das folgende Codebeispiel verwendet einen systemeigenen Abfrageparameter.

------
#### [ 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']
        }
    });
}());
```

------

Das folgende Codebeispiel verwendet einen Abfrageparameter vom Typ 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']
        }
    });
}());
```

------

Das folgende Codebeispiel verwendet mehrere Abfrageparameter.

------
#### [ 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']
        }
    });
}());
```

------

Das folgende Codebeispiel verwendet eine Liste von Abfrageparametern.

------
#### [ 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']
            */
        }
    });
}());
```

------

**Anmerkung**  
Wenn Sie eine Abfrage ohne indizierte Suche ausführen, wird ein vollständiger Tabellenscan aufgerufen. In diesem Beispiel empfehlen wir, einen [Index](ql-reference.create-index.md) für das `GovId` Feld zu verwenden, um die Leistung zu optimieren. Ohne aktivierten `GovId` Index können Abfragen eine höhere Latenz haben und auch zu OCC-Konfliktausnahmen oder Transaktions-Timeouts führen.

### Dokumente werden eingefügt
<a name="cookbook-nodejs.crud.inserting"></a>

Im folgenden Codebeispiel werden systemeigene Datentypen eingefügt.

------
#### [ 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);
        }
    });
}());
```

------

Im folgenden Codebeispiel werden Ion-Datentypen eingefügt.

------
#### [ 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);
        }
    });
}());
```

------

Diese Transaktion fügt ein Dokument in die `Person` Tabelle ein. Vor dem Einfügen wird zunächst geprüft, ob das Dokument bereits in der Tabelle vorhanden ist. **Diese Prüfung macht die Transaktion ihrem Wesen nach idempotent.** Selbst wenn Sie diese Transaktion mehrmals ausführen, hat sie keine unbeabsichtigten Nebenwirkungen.

**Anmerkung**  
In diesem Beispiel empfehlen wir, einen Index für das `GovId` Feld zu verwenden, um die Leistung zu optimieren. Ohne aktivierten `GovId` Index können Anweisungen eine längere Latenz haben und auch zu OCC-Konfliktausnahmen oder Transaktions-Timeouts führen.

#### Einfügen mehrerer Dokumente in eine Anweisung
<a name="cookbook-nodejs.crud.inserting.multiple"></a>

Um mehrere Dokumente mit einer einzigen [INSERT](ql-reference.insert.md) Anweisung einzufügen, können Sie der Anweisung wie folgt einen Parameter vom Typ [list](driver-working-with-ion.md#driver-ion-list) übergeben.

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

Sie setzen den Platzhalter für die Variable (`?`) nicht in doppelte spitze Klammern (`<<...>>`), wenn Sie eine Liste übergeben. *In manuellen PartiQL-Anweisungen bezeichnen doppelte spitze Klammern eine ungeordnete Sammlung, die als Tasche bezeichnet wird.*

### Dokumente werden aktualisiert
<a name="cookbook-nodejs.crud.updating"></a>

Das folgende Codebeispiel verwendet native Datentypen.

------
#### [ 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');
    });
}());
```

------

Das folgende Codebeispiel verwendet Ion-Datentypen.

------
#### [ 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);
    });
}());
```

------

**Anmerkung**  
In diesem Beispiel empfehlen wir, einen Index für das `GovId` Feld zu verwenden, um die Leistung zu optimieren. Ohne aktivierten `GovId` Index können Anweisungen eine längere Latenz haben und auch zu OCC-Konfliktausnahmen oder Transaktions-Timeouts führen.

### Dokumente löschen
<a name="cookbook-nodejs.crud.deleting"></a>

Das folgende Codebeispiel verwendet native Datentypen.

------
#### [ 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');
    });
}());
```

------

Das folgende Codebeispiel verwendet Ion-Datentypen.

------
#### [ 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);
    });
}());
```

------

**Anmerkung**  
In diesem Beispiel empfehlen wir, einen Index für das `GovId` Feld zu verwenden, um die Leistung zu optimieren. Ohne aktivierten `GovId` Index können Anweisungen eine längere Latenz haben und auch zu OCC-Konfliktausnahmen oder Transaktions-Timeouts führen.

### Ausführung mehrerer Anweisungen in einer Transaktion
<a name="cookbook-nodejs.crud.multi-statement"></a>

------
#### [ 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;
    });
};
```

------

### Logik für Wiederholversuche
<a name="cookbook-nodejs.crud.retry-logic"></a>

Die `executeLambda` Treibermethode verfügt über einen integrierten Wiederholungsmechanismus, der die Transaktion wiederholt, wenn eine Ausnahme auftritt, die wiederholt werden kann (z. B. Timeouts oder OCC-Konflikte). Die maximale Anzahl von Wiederholungsversuchen und die Backoff-Strategie sind konfigurierbar.

Das Standardlimit für Wiederholungsversuche ist`4`, und die Standard-Backoff-Strategie basiert [defaultBackoffFunction](https://amazon-qldb-docs.s3.amazonaws.com/drivers/nodejs/2.2.0/modules/_src_retry_defaultretryconfig_.html#defaultretryconfig)auf einer Basis von Millisekunden. `10` Sie können die Wiederholungskonfiguration pro Treiberinstanz und auch pro Transaktion festlegen, indem Sie eine Instanz von verwenden. [RetryConfig](https://amazon-qldb-docs.s3.amazonaws.com/drivers/nodejs/2.2.0/classes/_src_retry_retryconfig_.retryconfig.html)

Das folgende Codebeispiel spezifiziert die Wiederholungslogik mit einem benutzerdefinierten Wiederholungslimit und einer benutzerdefinierten Backoff-Strategie für eine Instanz des Treibers.

------
#### [ 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);
```

------

Das folgende Codebeispiel spezifiziert die Wiederholungslogik mit einem benutzerdefinierten Wiederholungslimit und einer benutzerdefinierten Backoff-Strategie für eine bestimmte Lambda-Ausführung. Diese Konfiguration für `executeLambda` überschreibt die Wiederholungslogik, die für die Treiberinstanz festgelegt ist.

------
#### [ 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);
}());
```

------

### Implementierung von Eindeutigkeitsbeschränkungen
<a name="cookbook-nodejs.crud.uniqueness-constraints"></a>

QLDB unterstützt keine eindeutigen Indizes, aber Sie können dieses Verhalten in Ihrer Anwendung implementieren.

Angenommen, Sie möchten eine Eindeutigkeitsbeschränkung für das `GovId` Feld in der Tabelle implementieren. `Person` Zu diesem Zweck können Sie eine Transaktion schreiben, die Folgendes tut:

1. Bestätigen Sie, dass die Tabelle keine vorhandenen Dokumente mit einem angegebenen Wert enthält`GovId`.

1. Fügt das Dokument ein, wenn die Assertion erfolgreich ist.

Wenn eine konkurrierende Transaktion gleichzeitig die Assertion besteht, wird nur eine der Transaktionen erfolgreich festgeschrieben. Die andere Transaktion schlägt mit einer OCC-Konfliktausnahme fehl.

Das folgende Codebeispiel zeigt, wie diese Eindeutigkeitsbeschränkungslogik implementiert wird.

------
#### [ 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);
        }
    });
})();
```

------

**Anmerkung**  
In diesem Beispiel empfehlen wir, einen Index für das `GovId` Feld zu verwenden, um die Leistung zu optimieren. Ohne aktivierten `GovId` Index können Anweisungen eine längere Latenz haben und auch zu OCC-Konfliktausnahmen oder Transaktions-Timeouts führen.

## Arbeiten mit Amazon Ion
<a name="cookbook-nodejs.ion"></a>

In den folgenden Abschnitten wird gezeigt, wie das Amazon Ion-Modul zur Verarbeitung von Ion-Daten verwendet wird.

**Contents**
+ [Das Ion-Modul importieren](#cookbook-nodejs.ion.import)
+ [Ion-Typen erstellen](#cookbook-nodejs.ion.creating-types)
+ [Einen Ion-Binär-Dump abrufen](#cookbook-nodejs.ion.getting-binary)
+ [Einen Ion-Textdump abrufen](#cookbook-nodejs.ion.getting-text)

### Das Ion-Modul importieren
<a name="cookbook-nodejs.ion.import"></a>

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

```
var ionjs = require('ion-js');
```

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

```
import { dom, dumpBinary, dumpText, load } from "ion-js";
```

------

### Ion-Typen erstellen
<a name="cookbook-nodejs.ion.creating-types"></a>

Im folgenden Codebeispiel wird ein Ion-Objekt aus Ion-Text erstellt.

------
#### [ 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']
```

------

Im folgenden Codebeispiel wird ein Ion-Objekt aus einem Node.js -Wörterbuch erstellt.

------
#### [ 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']
```

------

### Einen Ion-Binär-Dump abrufen
<a name="cookbook-nodejs.ion.getting-binary"></a>

------
#### [ 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
```

------

### Einen Ion-Textdump abrufen
<a name="cookbook-nodejs.ion.getting-text"></a>

------
#### [ 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"}
```

------

Weitere Informationen zu Ion finden Sie in der [Amazon Ion-Dokumentation](http://amzn.github.io/ion-docs/) unter GitHub. Weitere Codebeispiele für die Arbeit mit Ion in QLDB finden Sie unter. [Arbeiten mit Amazon Ion-Datentypen in Amazon QLDB](driver-working-with-ion.md)