

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.

# Verwenden von DynamoDB-Batchoperationen in AWS AppSync
<a name="tutorial-dynamodb-batch-js"></a>

AWS AppSync unterstützt die Verwendung von Amazon DynamoDB-Batchoperationen für eine oder mehrere Tabellen in einer einzigen Region. Zu den unterstützten Vorgängen gehören `BatchGetItem`, `BatchPutItem` und `BatchDeleteItem`. Mithilfe dieser Funktionen können Sie Aufgaben wie die folgenden ausführen: AWS AppSync
+ Übergeben einer Schlüsselliste in einer einzigen Abfrage und Rückgabe der Ergebnisse aus einer Tabelle
+ Lesen von Datensätzen aus einer oder mehreren Tabellen in einer einzigen Abfrage
+ Speichern von Datensätzen in großen Mengen in eine oder mehrere Tabellen
+ Bedingtes Schreiben oder Löschen von Datensätzen in mehreren Tabellen, die möglicherweise eine Beziehung haben

Batch-Operationen AWS AppSync weisen zwei wesentliche Unterschiede zu Vorgängen ohne Batch auf:
+ Die Datenquellenrolle muss über Berechtigungen für alle Tabellen verfügen, auf die der Resolver zugreift.
+ Die Tabellenspezifikation für einen Resolver ist Teil des Anforderungsobjekts.

## Batches aus einzelnen Tabellen
<a name="single-table-batch-js"></a>

**Warnung**  
`BatchPutItem`und `BatchDeleteItem` werden nicht unterstützt, wenn sie zusammen mit der Konflikterkennung und -lösung verwendet werden. Diese Einstellungen müssen deaktiviert werden, um mögliche Fehler zu vermeiden.

Lassen Sie uns zunächst eine neue GraphQL-API erstellen. Wählen Sie in der AWS AppSync Konsole **Create API**, **GraphQL APIs** und **Design from scratch aus**. **Geben Sie Ihrer API einen Namen`BatchTutorial API`, wählen Sie **Weiter** und wählen **Sie im Schritt GraphQL-Ressourcen angeben** die Option **GraphQL-Ressourcen später erstellen** aus und klicken Sie auf Weiter.** Überprüfen Sie Ihre Daten und erstellen Sie die API. Gehen Sie zur **Schema-Seite** und fügen Sie das folgende Schema ein. Beachten Sie dabei, dass wir für die Abfrage eine Liste mit folgenden Elementen übergeben IDs:

```
type Post {
    id: ID!
    title: String
}

input PostInput {
    id: ID!
    title: String
}

type Query {
    batchGet(ids: [ID]): [Post]
}

type Mutation {
    batchAdd(posts: [PostInput]): [Post]
    batchDelete(ids: [ID]): [Post]
}
```

Speichern Sie Ihr Schema und wählen Sie oben auf der Seite **Ressourcen erstellen** aus. Wählen Sie **Bestehenden Typ verwenden** und wählen Sie den `Post` Typ aus. Benennen Sie Ihre Tabelle`Posts`. **Stellen Sie sicher, dass der **Primärschlüssel** auf eingestellt ist`id`, deaktivieren Sie die Option **GraphQL automatisch generieren** (Sie geben Ihren eigenen Code an) und wählen Sie Erstellen aus.** AWS AppSync Erstellt zunächst eine neue DynamoDB-Tabelle und eine mit der Tabelle verbundene Datenquelle mit den entsprechenden Rollen. Es gibt jedoch noch einige Berechtigungen, die Sie der Rolle hinzufügen müssen. Gehen Sie zur Seite **Datenquellen** und wählen Sie die neue Datenquelle aus. Unter **Wählen Sie eine vorhandene Rolle** aus werden Sie feststellen, dass automatisch eine Rolle für die Tabelle erstellt wurde. Notieren Sie sich die Rolle (sollte ungefähr so aussehen`appsync-ds-ddb-aaabbbcccddd-Posts`) und wechseln Sie dann zur IAM-Konsole ([https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/)). Wählen Sie in der IAM-Konsole **Rollen** und dann Ihre Rolle aus der Tabelle aus. Klicken Sie in Ihrer Rolle unter **Berechtigungsrichtlinien** auf das "`+`" neben der Richtlinie (sollte einen ähnlichen Namen wie der Rollenname haben). Wenn die Richtlinie angezeigt wird, wählen Sie oben in der zusammenklappbaren Ansicht die Option **Bearbeiten** aus. Sie müssen Ihrer Richtlinie Batch-Berechtigungen hinzufügen, insbesondere `dynamodb:BatchGetItem` und`dynamodb:BatchWriteItem`. Es wird ungefähr so aussehen:

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:DeleteItem",
                "dynamodb:GetItem",
                "dynamodb:PutItem",
                "dynamodb:Query",
                "dynamodb:Scan",
                "dynamodb:UpdateItem",
                "dynamodb:BatchWriteItem",
                "dynamodb:BatchGetItem"
            ],
            "Resource": [
                "arn:aws:dynamodb:us-east-1:111122223333:table/locationReadings",
                "arn:aws:dynamodb:us-east-1:111122223333:table/locationReadings/*",
                "arn:aws:dynamodb:us-east-1:111122223333:table/temperatureReadings",
                "arn:aws:dynamodb:us-east-1:111122223333:table/temperatureReadings/*"
            ]
        }
    ]
}
```

------

Wählen Sie **Weiter** und dann **Änderungen speichern**. Ihre Richtlinie sollte jetzt die Stapelverarbeitung zulassen.

Gehen Sie zurück in der AWS AppSync Konsole zur **Schemaseite** und wählen Sie neben dem `Mutation.batchAdd` Feld die Option **Anhängen** aus. Erstellen Sie Ihren Resolver mit der `Posts` Tabelle als Datenquelle. Ersetzen Sie im Code-Editor die Handler durch das folgende Snippet. Dieses Snippet nimmt automatisch jedes Element `input PostInput` vom Typ GraphQL und erstellt eine Map, die für den Vorgang benötigt wird: `BatchPutItem`

```
import { util } from "@aws-appsync/utils";

export function request(ctx) {
  return {
    operation: "BatchPutItem",
    tables: {
      Posts: ctx.args.posts.map((post) => util.dynamodb.toMapValues(post)),
    },
  };
}

export function response(ctx) {
  if (ctx.error) {
    util.error(ctx.error.message, ctx.error.type);
  }
  return ctx.result.data.Posts;
}
```

Navigieren Sie zur Seite „**Abfragen**“ der AWS AppSync Konsole und führen Sie die folgende Mutation aus: `batchAdd`

```
mutation add {
    batchAdd(posts:[{
            id: 1 title: "Running in the Park"},{
            id: 2 title: "Playing fetch"
        }]){
            id
            title
    }
}
```

Sie sollten die Ergebnisse auf dem Bildschirm sehen. Sie können dies überprüfen, indem Sie die DynamoDB-Konsole überprüfen, um nach den in die Tabelle geschriebenen Werten zu suchen. `Posts`

Als Nächstes wiederholen Sie den Vorgang des Anfügens eines Resolvers, jedoch für das `Query.batchGet` Feld, wobei die `Posts` Tabelle als Datenquelle verwendet wird. Ersetzen Sie die Handler durch den folgenden Code. Hierdurch wird automatisch jedes Element im GraphQL `ids:[]`-Typ berücksichtigt und eine Zuordnung erstellt, wie sie für die `BatchGetItem`-Operation erforderlich ist:

```
import { util } from "@aws-appsync/utils";

export function request(ctx) {
  return {
    operation: "BatchGetItem",
    tables: {
      Posts: {
        keys: ctx.args.ids.map((id) => util.dynamodb.toMapValues({ id })),
        consistentRead: true,
      },
    },
  };
}

export function response(ctx) {
  if (ctx.error) {
    util.error(ctx.error.message, ctx.error.type);
  }
  return ctx.result.data.Posts;
}
```

**Gehen Sie jetzt zurück zur Abfrageseite der AWS AppSync Konsole und führen Sie die folgende `batchGet` Abfrage aus:**

```
query get {
    batchGet(ids:[1,2,3]){
        id
        title
    }
}
```

Dies sollte die Ergebnisse für die beiden `id`-Werte, die Sie zuvor hinzugefügt haben, zurückgeben. Beachten Sie, dass für den ein `null` Wert `id` mit dem Wert von zurückgegeben wurde`3`. Das liegt daran, dass es in Ihrer `Posts` Tabelle noch keinen Datensatz mit diesem Wert gab. Beachten Sie außerdem, dass die Ergebnisse in derselben Reihenfolge AWS AppSync zurückgegeben werden wie die an die Abfrage übergebenen Schlüssel. Dies ist eine zusätzliche Funktion, die AWS AppSync in Ihrem Namen ausgeführt wird. Wenn Sie also zu wechseln`batchGet(ids:[1,3,2])`, werden Sie feststellen, dass sich die Reihenfolge geändert hat. Sie können darüber hinaus erkennen, welche `id` einen `null`-Wert zurückgegeben hat.

Fügen Sie abschließend einen weiteren Resolver an das `Mutation.batchDelete` Feld an, indem Sie die `Posts` Tabelle als Datenquelle verwenden. Ersetzen Sie die Handler durch den folgenden Code. Hierdurch wird automatisch jedes Element im GraphQL `ids:[]`-Typ berücksichtigt und eine Zuordnung erstellt, wie sie für die `BatchGetItem`-Operation erforderlich ist:

```
import { util } from "@aws-appsync/utils";

export function request(ctx) {
  return {
    operation: "BatchDeleteItem",
    tables: {
      Posts: ctx.args.ids.map((id) => util.dynamodb.toMapValues({ id })),
    },
  };
}

export function response(ctx) {
  if (ctx.error) {
    util.error(ctx.error.message, ctx.error.type);
  }
  return ctx.result.data.Posts;
}
```

Gehen Sie jetzt zurück zur **Abfrageseite** der AWS AppSync Konsole und führen Sie die folgende `batchDelete` Mutation aus:

```
mutation delete {
    batchDelete(ids:[1,2]){ id }
}
```

Die Datensätze mit der `id` `1` und `2` sollten jetzt gelöscht sein. Wenn Sie die frühere `batchGet()`-Abfrage ausführen, sollten diese `null` zurückgeben.

## Batch mit mehreren Tabellen
<a name="multi-table-batch-js"></a>

**Warnung**  
`BatchPutItem`und `BatchDeleteItem` werden nicht unterstützt, wenn sie zusammen mit der Konflikterkennung und -lösung verwendet werden. Diese Einstellungen müssen deaktiviert werden, um mögliche Fehler zu vermeiden.

AWS AppSync ermöglicht es Ihnen auch, tabellenübergreifende Batch-Operationen durchzuführen. Lassen Sie uns hierzu eine komplexere Anwendung erstellen. Stellen Sie sich vor, wir entwickeln eine App zur Tiergesundheit, bei der Sensoren den Standort und die Körpertemperatur des Tieres melden. Diese Sensoren sind batteriebetrieben und versuchen, alle paar Minuten eine Verbindung mit dem Netzwerk aufzubauen. Wenn ein Sensor eine Verbindung herstellt, sendet er seine Messwerte an unsere AWS AppSync API. Die Daten werden von Auslösern analysiert und dem Besitzer des Haustiers in einem Dashboard angezeigt. Lassen Sie uns jetzt die Interaktionen zwischen dem Sensor und dem Backend-Datenspeicher näher untersuchen.

Wählen Sie in der AWS AppSync Konsole **Create API**, **GraphQL APIs** und **Design from scratch aus**. **Geben Sie Ihrer API einen Namen`MultiBatchTutorial API`, wählen Sie **Weiter** und wählen **Sie im Schritt GraphQL-Ressourcen angeben** die Option **GraphQL-Ressourcen später erstellen** aus und klicken Sie auf Weiter.** Überprüfen Sie Ihre Daten und erstellen Sie die API. Gehen Sie zur **Schema-Seite** und fügen Sie das folgende Schema ein und speichern Sie es:

```
type Mutation {
    # Register a batch of readings
    recordReadings(tempReadings: [TemperatureReadingInput], locReadings: [LocationReadingInput]): RecordResult
    # Delete a batch of readings
    deleteReadings(tempReadings: [TemperatureReadingInput], locReadings: [LocationReadingInput]): RecordResult
}

type Query {
    # Retrieve all possible readings recorded by a sensor at a specific time
    getReadings(sensorId: ID!, timestamp: String!): [SensorReading]
}

type RecordResult {
    temperatureReadings: [TemperatureReading]
    locationReadings: [LocationReading]
}

interface SensorReading {
    sensorId: ID!
    timestamp: String!
}

# Sensor reading representing the sensor temperature (in Fahrenheit)
type TemperatureReading implements SensorReading {
    sensorId: ID!
    timestamp: String!
    value: Float
}

# Sensor reading representing the sensor location (lat,long)
type LocationReading implements SensorReading {
    sensorId: ID!
    timestamp: String!
    lat: Float
    long: Float
}

input TemperatureReadingInput {
    sensorId: ID!
    timestamp: String
    value: Float
}

input LocationReadingInput {
    sensorId: ID!
    timestamp: String
    lat: Float
    long: Float
}
```

Wir müssen zwei DynamoDB-Tabellen erstellen:
+ `locationReadings`speichert die Messwerte der Sensorposition.
+ `temperatureReadings`speichert die Sensortemperaturwerte.

Beide Tabellen werden dieselbe Primärschlüsselstruktur haben: `sensorId (String)` als Partitionsschlüssel und `timestamp (String)` als Sortierschlüssel.

Wählen Sie oben auf der Seite **Create Resources** aus. Wählen Sie **Bestehenden Typ verwenden** und wählen Sie den `locationReadings` Typ aus. Benennen Sie Ihre Tabelle`locationReadings`. Stellen Sie sicher, dass der **Primärschlüssel** auf `sensorId` und der Sortierschlüssel auf eingestellt sind`timestamp`. **Deaktivieren Sie die Option **GraphQL automatisch generieren** (Sie stellen Ihren eigenen Code bereit) und wählen Sie Erstellen aus.** Wiederholen Sie diesen Vorgang, um den `temperatureReadings` als Typ und Tabellennamen zu `temperatureReadings` verwenden. Verwenden Sie dieselben Tasten wie oben.

Ihre neuen Tabellen werden automatisch generierte Rollen enthalten. Es gibt noch einige Berechtigungen, die Sie diesen Rollen hinzufügen müssen. Gehen Sie zur Seite **Datenquellen** und wählen Sie`locationReadings`. Unter **Wählen Sie eine bestehende Rolle** aus können Sie die Rolle sehen. Notieren Sie sich die Rolle (sollte ungefähr so aussehen`appsync-ds-ddb-aaabbbcccddd-locationReadings`) und wechseln Sie dann zur IAM-Konsole ([https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/)). Wählen Sie in der IAM-Konsole **Rollen** und dann Ihre Rolle aus der Tabelle aus. Klicken Sie in Ihrer Rolle unter **Berechtigungsrichtlinien** auf das "`+`" neben der Richtlinie (sollte einen ähnlichen Namen wie der Rollenname haben). Wenn die Richtlinie angezeigt wird, wählen Sie oben in der zusammenklappbaren Ansicht die Option **Bearbeiten** aus. Sie müssen dieser Richtlinie Berechtigungen hinzufügen. Es wird ungefähr so aussehen:

Wählen Sie **Weiter** und dann **Änderungen speichern**. Wiederholen Sie diesen Vorgang für die `temperatureReadings` Datenquelle mit demselben Richtlinienausschnitt oben.

### BatchPutItem - Aufzeichnen von Sensormesswerten
<a name="batchputitem-recording-sensor-readings-js"></a>

Nachdem eine Verbindung zum Internet hergestellt wurde, müssen unsere Sensoren in der Lage sein, ihre Messwerte zu senden. Sie verwenden dazu die API GraphQL-Feld `Mutation.recordReadings`. Wir müssen diesem Feld einen Resolver hinzufügen.

Wählen Sie auf der **Schemaseite** der AWS AppSync Konsole neben dem `Mutation.recordReadings` Feld die Option **Anhängen** aus. Erstellen Sie auf dem nächsten Bildschirm Ihren Resolver mit der `locationReadings` Tabelle als Datenquelle.

Nachdem Sie Ihren Resolver erstellt haben, ersetzen Sie die Handler im Editor durch den folgenden Code. Diese `BatchPutItem` Operation ermöglicht es uns, mehrere Tabellen anzugeben: 

```
import { util } from '@aws-appsync/utils'

export function request(ctx) {
	const { locReadings, tempReadings } = ctx.args
	const locationReadings = locReadings.map((loc) => util.dynamodb.toMapValues(loc))
	const temperatureReadings = tempReadings.map((tmp) => util.dynamodb.toMapValues(tmp))

	return {
		operation: 'BatchPutItem',
		tables: {
			locationReadings,
			temperatureReadings,
		},
	}
}

export function response(ctx) {
	if (ctx.error) {
		util.appendError(ctx.error.message, ctx.error.type)
	}
	return ctx.result.data
}
```

Bei Stapelvorgängen können durch den Aufruf sowohl Fehler als auch Ergebnisse zurückgegeben werden. In diesem Fall können wir eine zusätzliche Fehlerbehandlung vornehmen.

**Anmerkung**  
Die Verwendung von `utils.appendError()` ähnelt der`util.error()`, mit dem wesentlichen Unterschied, dass sie die Auswertung des Anfrage- oder Antworthandlers nicht unterbricht. Stattdessen signalisiert es, dass ein Fehler mit dem Feld aufgetreten ist, ermöglicht aber die Auswertung des Handlers und damit die Rückgabe von Daten an den Aufrufer. Wir empfehlen die Verwendung, `utils.appendError()` wenn Ihre Anwendung Teilergebnisse zurückgeben muss.

Speichern Sie den Resolver und navigieren Sie in der AWS AppSync Konsole zur Seite **Abfragen**. Wir können jetzt einige Sensorwerte senden.

Führen Sie die folgende Mutation aus:

```
mutation sendReadings {
  recordReadings(
    tempReadings: [
      {sensorId: 1, value: 85.5, timestamp: "2018-02-01T17:21:05.000+08:00"},
      {sensorId: 1, value: 85.7, timestamp: "2018-02-01T17:21:06.000+08:00"},
      {sensorId: 1, value: 85.8, timestamp: "2018-02-01T17:21:07.000+08:00"},
      {sensorId: 1, value: 84.2, timestamp: "2018-02-01T17:21:08.000+08:00"},
      {sensorId: 1, value: 81.5, timestamp: "2018-02-01T17:21:09.000+08:00"}
    ]
    locReadings: [
      {sensorId: 1, lat: 47.615063, long: -122.333551, timestamp: "2018-02-01T17:21:05.000+08:00"},
      {sensorId: 1, lat: 47.615163, long: -122.333552, timestamp: "2018-02-01T17:21:06.000+08:00"},
      {sensorId: 1, lat: 47.615263, long: -122.333553, timestamp: "2018-02-01T17:21:07.000+08:00"},
      {sensorId: 1, lat: 47.615363, long: -122.333554, timestamp: "2018-02-01T17:21:08.000+08:00"},
      {sensorId: 1, lat: 47.615463, long: -122.333555, timestamp: "2018-02-01T17:21:09.000+08:00"}
    ]) {
    locationReadings {
      sensorId
      timestamp
      lat
      long
    }
    temperatureReadings {
      sensorId
      timestamp
      value
    }
  }
}
```

Wir haben zehn Sensorwerte in einer Mutation gesendet, wobei die Messwerte auf zwei Tabellen aufgeteilt wurden. Verwenden Sie die DynamoDB-Konsole, um zu überprüfen, ob die Daten sowohl in der als auch in der `locationReadings` Tabelle angezeigt werden. `temperatureReadings`

### BatchDeleteItem - Löschen von Sensormesswerten
<a name="batchdeleteitem-deleting-sensor-readings-js"></a>

In ähnlicher Weise müssten wir auch in der Lage sein, Chargen von Sensormesswerten zu löschen. Dazu verwenden wir das GraphQL-Feld `Mutation.deleteReadings`. Wählen Sie auf der **Schemaseite** der AWS AppSync Konsole neben dem `Mutation.deleteReadings` Feld die Option **Anhängen** aus. Erstellen Sie auf dem nächsten Bildschirm Ihren Resolver mit der `locationReadings` Tabelle als Datenquelle.

Nachdem Sie Ihren Resolver erstellt haben, ersetzen Sie die Handler im Code-Editor durch das folgende Snippet. In diesem Resolver verwenden wir einen Hilfsfunktions-Mapper, der die `sensorId` und aus den bereitgestellten Eingaben extrahiert. `timestamp` 

```
import { util } from '@aws-appsync/utils'

export function request(ctx) {
	const { locReadings, tempReadings } = ctx.args
	const mapper = ({ sensorId, timestamp }) => util.dynamodb.toMapValues({ sensorId, timestamp })

	return {
		operation: 'BatchDeleteItem',
		tables: {
			locationReadings: locReadings.map(mapper),
			temperatureReadings: tempReadings.map(mapper),
		},
	}
}

export function response(ctx) {
	if (ctx.error) {
		util.appendError(ctx.error.message, ctx.error.type)
	}
	return ctx.result.data
}
```

Speichern Sie den Resolver und navigieren Sie zur Seite „**Abfragen**“ in der Konsole. AWS AppSync Lassen Sie uns nun ein paar Sensormesswerte löschen.

Führen Sie die folgende Mutation aus:

```
mutation deleteReadings {
  # Let's delete the first two readings we recorded
  deleteReadings(
    tempReadings: [{sensorId: 1, timestamp: "2018-02-01T17:21:05.000+08:00"}]
    locReadings: [{sensorId: 1, timestamp: "2018-02-01T17:21:05.000+08:00"}]) {
    locationReadings {
      sensorId
      timestamp
      lat
      long
    }
    temperatureReadings {
      sensorId
      timestamp
      value
    }
  }
}
```

**Anmerkung**  
Im Gegensatz zum `DeleteItem`-Vorgang wird nicht das vollständig gelöschte Element in der Antwort zurückgegeben. Nur der übergebene Schlüssel wird zurückgegeben. Weitere Informationen finden Sie [BatchDeleteItem in der JavaScript Resolver-Funktionsreferenz für DynamoDB](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-batch-delete-item).

Überprüfen Sie über die DynamoDB-Konsole, ob diese beiden Messwerte aus den Tabellen `locationReadings` und `temperatureReadings` gelöscht wurden.

### BatchGetItem - Messwerte abrufen
<a name="batchgetitem-retrieve-readings-js"></a>

Eine weitere übliche Operation für unsere App wäre das Abrufen der Messwerte für einen Sensor zu einem bestimmten Zeitpunkt. Fügen wir dazu einen Resolver zum GraphQL-Feld `Query.getReadings` unseres Schemas hinzu. Wählen Sie auf der **Schemaseite** der AWS AppSync Konsole neben dem `Query.getReadings` Feld die Option **Anhängen** aus. Erstellen Sie auf dem nächsten Bildschirm Ihren Resolver mit der `locationReadings` Tabelle als Datenquelle.

Lassen Sie uns den folgenden Code verwenden: 

```
import { util } from '@aws-appsync/utils'

export function request(ctx) {
	const keys = [util.dynamodb.toMapValues(ctx.args)]
	const consistentRead = true
	return {
		operation: 'BatchGetItem',
		tables: {
			locationReadings: { keys, consistentRead },
			temperatureReadings: { keys, consistentRead },
		},
	}
}

export function response(ctx) {
	if (ctx.error) {
		util.appendError(ctx.error.message, ctx.error.type)
	}
	const { locationReadings: locs, temperatureReadings: temps } = ctx.result.data

	return [
		...locs.map((l) => ({ ...l, __typename: 'LocationReading' })),
		...temps.map((t) => ({ ...t, __typename: 'TemperatureReading' })),
	]
}
```

Speichern Sie den Resolver und navigieren Sie zur Seite „**Abfragen**“ in der AWS AppSync Konsole. Lassen Sie uns nun unsere Sensorwerte abrufen.

Führen Sie die folgende Abfrage aus:

```
query getReadingsForSensorAndTime {
  # Let's retrieve the very first two readings
  getReadings(sensorId: 1, timestamp: "2018-02-01T17:21:06.000+08:00") {
    sensorId
    timestamp
    ...on TemperatureReading {
      value
    }
    ...on LocationReading {
      lat
      long
    }
  }
}
```

Wir haben erfolgreich die Verwendung von DynamoDB-Batchoperationen unter Verwendung von demonstriert. AWS AppSync

## Fehlerbehandlung
<a name="error-handling-js"></a>

In AWS AppSync Datenquellenoperationen können manchmal Teilergebnisse zurückgegeben werden. Wir verwenden den Begriff Teilergebnis, wenn bei der Ausgabe einer Operation einige Daten fehlen und darin ein Fehler enthalten ist. Da die Fehlerbehandlung von Natur aus anwendungsspezifisch ist, AWS AppSync haben Sie die Möglichkeit, Fehler im Antworthandler zu behandeln. Sollte beim Resolver ein Aufruffehler vorliegen, lässt sich dieser im Kontext an `ctx.error` erkennen. Aufruffehler umfassen immer eine Nachricht und eine Art, auf die über die Eigenschaften `ctx.error.message` und `ctx.error.type`zugegriffen werden kann. Im Antworthandler können Sie Teilergebnisse auf drei Arten verarbeiten:

1. Überwinden Sie den Aufruffehler, indem Sie einfach Daten zurückgeben.

1. Einen Fehler (using`util.error(...)`) auslösen, indem Sie die Auswertung des Handlers beenden, wodurch keine Daten zurückgegeben werden.

1. Fügt einen Fehler an (using`util.appendError(...)`) und gibt auch Daten zurück.

Lassen Sie uns jeden der drei oben genannten Punkte anhand von DynamoDB-Batchoperationen demonstrieren.

### DynamoDB-Stapelvorgänge
<a name="dynamodb-batch-operations-js"></a>

Mit DynamoDB-Stapelvorgängen ist es möglich, dass ein Stapel teilweise abgeschlossen wird. Das bedeutet, dass einige der angeforderten Elemente oder Schlüssel nicht verarbeitet werden. Wenn AWS AppSync ein Batch nicht abgeschlossen werden kann, werden unverarbeitete Elemente und ein Aufruffehler für den Kontext angezeigt.

Wir werden die Fehlerbehandlung mithilfe der `Query.getReadings`-Feldkonfiguration der `BatchGetItem`-Operation aus dem vorherigen Abschnitt dieser Anleitung implementieren. Dieses Mal nehmen wir jedoch an, dass bei der Ausführung des `Query.getReadings`-Felds die DynamoDB-Tabelle `temperatureReadings` den bereitgestellten Durchsatz überschritten hat. DynamoDB hat `ProvisionedThroughputExceededException` beim zweiten Versuch a ausgelöst, AWS AppSync um die verbleibenden Elemente im Stapel zu verarbeiten.

Das folgende JSON stellt den serialisierten Kontext nach dem DynamoDB-Batchaufruf, aber bevor der Antworthandler aufgerufen wurde, dar:

```
{
  "arguments": {
    "sensorId": "1",
    "timestamp": "2018-02-01T17:21:05.000+08:00"
  },
  "source": null,
  "result": {
    "data": {
      "temperatureReadings": [
        null
      ],
      "locationReadings": [
        {
          "lat": 47.615063,
          "long": -122.333551,
          "sensorId": "1",
          "timestamp": "2018-02-01T17:21:05.000+08:00"
        }
      ]
    },
    "unprocessedKeys": {
      "temperatureReadings": [
        {
          "sensorId": "1",
          "timestamp": "2018-02-01T17:21:05.000+08:00"
        }
      ],
      "locationReadings": []
    }
  },
  "error": {
    "type": "DynamoDB:ProvisionedThroughputExceededException",
    "message": "You exceeded your maximum allowed provisioned throughput for a table or for one or more global secondary indexes. (...)"
  },
  "outErrors": []
}
```

Beachten Sie in diesem Kontext die folgenden Dinge:
+ Der Aufruffehler wurde für den Kontext bei `ctx.error` by festgelegt AWS AppSync, und der Fehlertyp wurde auf gesetzt. `DynamoDB:ProvisionedThroughputExceededException`
+ Die Ergebnisse werden pro Tabelle unter zugeordnet, `ctx.result.data` obwohl ein Fehler vorliegt.
+ Schlüssel, die nicht verarbeitet wurden, sind unter verfügbar. `ctx.result.data.unprocessedKeys` Hier AWS AppSync konnte das Element mit dem Schlüssel (sensorId:1, timestamp:2018-02-01T 17:21:05.000 \$1 08:00) aufgrund des unzureichenden Tabellendurchsatzes nicht abgerufen werden.

**Anmerkung**  
Für `BatchPutItem` gilt `ctx.result.data.unprocessedItems`. Für `BatchDeleteItem` gilt `ctx.result.data.unprocessedKeys`.

Sie können mit diesem Fehler auf drei verschiedene Arten umgehen.

#### 1. Übergehen des Aufruffehlers
<a name="swallowing-the-invocation-error-js"></a>

Wenn Daten ohne Verarbeitung des Aufruffehlers zurückgegeben werden, wird der Fehler effektiv übergangen. Auf diese Weise ist das Ergebnis für das angegebene GraphQL-Feld immer erfolgreich.

Der Code, den wir schreiben, ist vertraut und konzentriert sich nur auf die Ergebnisdaten.

**Antworthandler**

```
export function response(ctx) {
  return ctx.result.data
}
```

**GraphQL-Antwort**

```
{
  "data": {
    "getReadings": [
      {
        "sensorId": "1",
        "timestamp": "2018-02-01T17:21:05.000+08:00",
        "lat": 47.615063,
        "long": -122.333551
      },
      {
        "sensorId": "1",
        "timestamp": "2018-02-01T17:21:05.000+08:00",
        "value": 85.5
      }
    ]
  }
}
```

Der Fehlerantwort werden keine Fehler hinzugefügt, da nur auf Daten reagiert wird.

#### 2. Es wird ein Fehler ausgelöst, um die Ausführung des Response-Handlers abzubrechen
<a name="raising-an-error-to-abort-the-response-execution-js"></a>

Wenn Teilausfälle aus Sicht des Clients als vollständige Fehler behandelt werden sollen, können Sie die Ausführung des Antworthandlers abbrechen, um zu verhindern, dass Daten zurückgegeben werden. Das Dienstprogramm `util.error(...)` erzielt genau dieses Verhalten.

**Code des Antworthandlers**

```
export function response(ctx) {
  if (ctx.error) {
    util.error(ctx.error.message, ctx.error.type, null, ctx.result.data.unprocessedKeys);
  }
  return ctx.result.data;
}
```

**GraphQL-Antwort**

```
{
  "data": {
    "getReadings": null
  },
  "errors": [
    {
      "path": [
        "getReadings"
      ],
      "data": null,
      "errorType": "DynamoDB:ProvisionedThroughputExceededException",
      "errorInfo": {
        "temperatureReadings": [
          {
            "sensorId": "1",
            "timestamp": "2018-02-01T17:21:05.000+08:00"
          }
        ],
        "locationReadings": []
      },
      "locations": [
        {
          "line": 58,
          "column": 3
        }
      ],
      "message": "You exceeded your maximum allowed provisioned throughput for a table or for one or more global secondary indexes. (...)"
    }
  ]
}
```

Auch wenn der DynamoDB Stapelvorgang möglicherweise einige Ergebnisse zurückgegeben hat, haben wir uns entschieden, einen Fehler zu melden, indem das GraphQL-Feld `getReadings` mit Null angezeigt und der Fehler dem *Fehler*-Block der GraphQL-Antwort hinzugefügt wurde.

#### 3. Anfügen eines Fehlers bei der Rückgabe von Daten und Fehlern
<a name="appending-an-error-to-return-both-data-and-errors-js"></a>

In bestimmten Fällen können Anwendungen Teilergebnisse zurückgeben und die Clients über die unverarbeiteten Elemente benachrichtigen und so die Benutzererfahrung verbessern. Die Clients können entscheiden, eine Wiederholung zu implementieren oder den Fehler an den Endbenutzer zu übermitteln. Dies `util.appendError(...)` ist die Hilfsmethode, die dieses Verhalten ermöglicht, indem sie es dem Anwendungsdesigner ermöglicht, Fehler an den Kontext anzuhängen, ohne die Auswertung des Antworthandlers zu beeinträchtigen. Nach der Auswertung des Antworthandlers AWS AppSync verarbeitet er alle Kontextfehler, indem er sie an den Fehlerblock der GraphQL-Antwort anhängt.

**Code für den Antworthandler**

```
export function response(ctx) {
  if (ctx.error) {
    util.appendError(ctx.error.message, ctx.error.type, null, ctx.result.data.unprocessedKeys);
  }
  return ctx.result.data;
}
```

Wir haben sowohl den Aufruffehler als auch `unprocessedKeys` das Element innerhalb des Fehlerblocks der GraphQL-Antwort weitergeleitet. Das `getReadings` Feld gibt auch Teildaten aus der `locationReadings` Tabelle zurück, wie Sie in der folgenden Antwort sehen können.

**GraphQL-Antwort**

```
{
  "data": {
    "getReadings": [
      null,
      {
        "sensorId": "1",
        "timestamp": "2018-02-01T17:21:05.000+08:00",
        "value": 85.5
      }
    ]
  },
  "errors": [
    {
      "path": [
        "getReadings"
      ],
      "data": null,
      "errorType": "DynamoDB:ProvisionedThroughputExceededException",
      "errorInfo": {
        "temperatureReadings": [
          {
            "sensorId": "1",
            "timestamp": "2018-02-01T17:21:05.000+08:00"
          }
        ],
        "locationReadings": []
      },
      "locations": [
        {
          "line": 58,
          "column": 3
        }
      ],
      "message": "You exceeded your maximum allowed provisioned throughput for a table or for one or more global secondary indexes. (...)"
    }
  ]
}
```