

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

# Menggunakan operasi batch DynamoDB di AWS AppSync
<a name="tutorial-dynamodb-batch"></a>

**catatan**  
Kami sekarang terutama mendukung runtime APPSYNC\$1JS dan dokumentasinya. [Harap pertimbangkan untuk menggunakan runtime APPSYNC\$1JS dan panduannya di sini.](https://docs.aws.amazon.com/appsync/latest/devguide/tutorials-js.html)

AWS AppSync mendukung penggunaan operasi batch Amazon DynamoDB di satu atau beberapa tabel dalam satu wilayah. Operasi yang didukung adalah`BatchGetItem`,`BatchPutItem`, dan`BatchDeleteItem`. Dengan menggunakan fitur-fitur ini di AWS AppSync, Anda dapat melakukan tugas-tugas seperti:
+ Lewati daftar kunci dalam satu kueri dan kembalikan hasil dari tabel
+ Membaca catatan dari satu atau beberapa tabel dalam satu kueri
+ Tulis catatan secara massal ke satu atau lebih tabel
+ Menulis atau menghapus catatan secara kondisional dalam beberapa tabel yang mungkin memiliki hubungan

Menggunakan operasi batch dengan DynamoDB AWS AppSync in adalah teknik canggih yang membutuhkan sedikit pemikiran dan pengetahuan ekstra tentang operasi backend dan struktur tabel Anda. Selain itu, operasi batch AWS AppSync memiliki dua perbedaan utama dari operasi non-batch:
+ Peran sumber data harus memiliki izin ke semua tabel yang akan diakses oleh resolver.
+ Spesifikasi tabel untuk resolver adalah bagian dari template pemetaan.

## Izin
<a name="permissions"></a>

Seperti resolver lainnya, Anda perlu membuat sumber data AWS AppSync dan membuat peran atau menggunakan yang sudah ada. Karena operasi batch memerlukan izin yang berbeda pada tabel DynamoDB, Anda perlu memberikan izin peran yang dikonfigurasi untuk tindakan baca atau tulis:

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Action": [
                "dynamodb:BatchGetItem",
                "dynamodb:BatchWriteItem"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:dynamodb:us-east-1:111122223333:table/TABLENAME",
                "arn:aws:dynamodb:us-east-1:111122223333:table/TABLENAME/*"
            ]
        }
    ]
}
```

------

 **Catatan**: Peran terkait dengan sumber data di AWS AppSync, dan resolver pada bidang dipanggil terhadap sumber data. Sumber data yang dikonfigurasi untuk mengambil terhadap DynamoDB hanya memiliki satu tabel yang ditentukan, untuk menjaga konfigurasi tetap sederhana. Oleh karena itu, saat melakukan operasi batch terhadap beberapa tabel dalam satu resolver, yang merupakan tugas yang lebih maju, Anda harus memberikan peran pada akses sumber data tersebut ke tabel mana pun yang akan berinteraksi dengan resolver. Ini akan dilakukan di bidang **Sumber Daya** dalam kebijakan IAM di atas. Konfigurasi tabel untuk membuat panggilan batch terhadap dilakukan dalam template resolver, yang kami jelaskan di bawah ini.

## Sumber Data
<a name="data-source"></a>

Demi kesederhanaan, kita akan menggunakan sumber data yang sama untuk semua resolver yang digunakan dalam tutorial ini. Pada tab **Sumber data**, buat sumber data DynamoDB baru dan beri nama. **BatchTutorial** Nama tabel dapat berupa apa saja karena nama tabel ditentukan sebagai bagian dari template pemetaan permintaan untuk operasi batch. Kami akan memberikan nama tabel`empty`.

Untuk tutorial ini, peran apa pun dengan kebijakan inline berikut akan berfungsi:

## Batch Tabel Tunggal
<a name="single-table-batch"></a>

**Awas**  
`BatchPutItem`dan `BatchDeleteItem` tidak didukung saat digunakan dengan deteksi dan resolusi konflik. Pengaturan ini harus dinonaktifkan untuk mencegah kemungkinan kesalahan.

Untuk contoh ini, misalkan Anda memiliki satu tabel bernama **Posts** yang ingin Anda tambahkan dan hapus item dengan operasi batch. Gunakan skema berikut, perhatikan bahwa untuk kueri, kita akan meneruskan daftar 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]
}

schema {
    query: Query
    mutation: Mutation
}
```

Lampirkan resolver ke `batchAdd()` bidang dengan Template **Pemetaan Permintaan** berikut. Ini secara otomatis mengambil setiap item dalam tipe `input PostInput` GraphQL dan membangun peta, yang diperlukan untuk operasi: `BatchPutItem`

```
#set($postsdata = [])
#foreach($item in ${ctx.args.posts})
    $util.qr($postsdata.add($util.dynamodb.toMapValues($item)))
#end

{
    "version" : "2018-05-29",
    "operation" : "BatchPutItem",
    "tables" : {
        "Posts": $utils.toJson($postsdata)
    }
}
```

Dalam hal ini, **Response Mapping Template** adalah passthrough sederhana, tetapi nama tabel ditambahkan `..data.Posts` ke objek konteks sebagai berikut:

```
$util.toJson($ctx.result.data.Posts)
```

Sekarang navigasikan ke halaman **Kueri** AWS AppSync konsol dan jalankan mutasi **batchAdd** berikut:

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

**Anda akan melihat hasil yang dicetak ke layar, dan dapat secara independen memvalidasi melalui konsol DynamoDB yang ditulis oleh kedua nilai ke tabel Posts.**

Selanjutnya, lampirkan resolver ke `batchGet()` bidang dengan Template **Pemetaan Permintaan** berikut. Ini secara otomatis mengambil setiap item dalam tipe `ids:[]` GraphQL dan membangun peta yang diperlukan untuk operasi: `BatchGetItem`

```
#set($ids = [])
#foreach($id in ${ctx.args.ids})
    #set($map = {})
    $util.qr($map.put("id", $util.dynamodb.toString($id)))
    $util.qr($ids.add($map))
#end

{
    "version" : "2018-05-29",
    "operation" : "BatchGetItem",
    "tables" : {
        "Posts": {
            "keys": $util.toJson($ids),
            "consistentRead": true,
            "projection" : {
                "expression" : "#id, title",
                "expressionNames" : { "#id" : "id"}
                }
        }
    }
}
```

**Template Pemetaan Respons** sekali lagi merupakan passthrough sederhana, dengan sekali lagi nama tabel ditambahkan `..data.Posts` ke objek konteks:

```
$util.toJson($ctx.result.data.Posts)
```

Sekarang kembali ke halaman **Queries** AWS AppSync konsol, dan jalankan **BatchGet** Query berikut:

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

Ini akan mengembalikan hasil untuk dua `id` nilai yang Anda tambahkan sebelumnya. Perhatikan bahwa `null` nilai yang dikembalikan untuk `id` dengan nilai`3`. Ini karena belum ada catatan di tabel **Posts** Anda dengan nilai itu. Perhatikan juga bahwa AWS AppSync mengembalikan hasil dalam urutan yang sama dengan kunci yang diteruskan ke kueri, yang merupakan fitur tambahan yang AWS AppSync dilakukan atas nama Anda. Jadi jika Anda beralih ke`batchGet(ids:[1,3,2)`, Anda akan melihat urutannya berubah. Anda juga akan tahu mana yang `id` mengembalikan `null` nilai.

Terakhir, lampirkan resolver ke `batchDelete()` bidang dengan Template **Pemetaan Permintaan** berikut. Ini secara otomatis mengambil setiap item dalam tipe `ids:[]` GraphQL dan membangun peta yang diperlukan untuk operasi: `BatchGetItem`

```
#set($ids = [])
#foreach($id in ${ctx.args.ids})
    #set($map = {})
    $util.qr($map.put("id", $util.dynamodb.toString($id)))
    $util.qr($ids.add($map))
#end

{
    "version" : "2018-05-29",
    "operation" : "BatchDeleteItem",
    "tables" : {
        "Posts": $util.toJson($ids)
    }
}
```

**Template Pemetaan Respons** sekali lagi merupakan passthrough sederhana, dengan sekali lagi nama tabel ditambahkan `..data.Posts` ke objek konteks:

```
$util.toJson($ctx.result.data.Posts)
```

Sekarang kembali ke halaman **Queries** AWS AppSync konsol, dan jalankan mutasi **BatchDelete** berikut:

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

Catatan dengan `id` `1` dan sekarang `2` harus dihapus. Jika Anda menjalankan kembali `batchGet()` kueri dari sebelumnya, ini akan kembali`null`.

## Batch Multi-Tabel
<a name="multi-table-batch"></a>

**Awas**  
`BatchPutItem`dan `BatchDeleteItem` tidak didukung saat digunakan dengan deteksi dan resolusi konflik. Pengaturan ini harus dinonaktifkan untuk mencegah kemungkinan kesalahan.

AWS AppSync juga memungkinkan Anda untuk melakukan operasi batch di seluruh tabel. Mari kita membangun aplikasi yang lebih kompleks. Bayangkan kita sedang membangun aplikasi Kesehatan Hewan Peliharaan, di mana sensor melaporkan lokasi hewan peliharaan dan suhu tubuh. Sensor bertenaga baterai dan mencoba untuk terhubung ke jaringan setiap beberapa menit. Ketika sensor membuat koneksi, ia mengirimkan bacaannya ke AWS AppSync API kami. Pemicu kemudian menganalisis data sehingga dasbor dapat disajikan kepada pemilik hewan peliharaan. Mari kita fokus pada merepresentasikan interaksi antara sensor dan penyimpanan data backend.

**Sebagai prasyarat, pertama-tama mari kita buat dua tabel DynamoDB; LocationReadings akan menyimpan pembacaan lokasi sensor dan TemperatureReadings **akan** menyimpan pembacaan suhu sensor.** Kedua tabel kebetulan berbagi struktur kunci utama yang sama: `sensorId (String)` menjadi kunci partisi, dan `timestamp (String)` kunci sortir.

Mari kita gunakan skema GraphQL berikut:

```
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
}
```

### BatchPutItem - Bacaan Sensor Perekaman
<a name="batchputitem-recording-sensor-readings"></a>

Sensor kami harus dapat mengirim bacaan mereka setelah mereka terhubung ke internet. `Mutation.recordReadings`Bidang GraphQL adalah API yang akan mereka gunakan untuk melakukannya. Mari lampirkan resolver untuk menghidupkan API kita.

Pilih **Lampirkan** di sebelah `Mutation.recordReadings` bidang. Pada layar berikutnya, pilih sumber `BatchTutorial` data yang sama yang dibuat di awal tutorial.

Mari tambahkan template pemetaan permintaan berikut:

 **Templat Pemetaan Permintaan** 

```
## Convert tempReadings arguments to DynamoDB objects
#set($tempReadings = [])
#foreach($reading in ${ctx.args.tempReadings})
    $util.qr($tempReadings.add($util.dynamodb.toMapValues($reading)))
#end

## Convert locReadings arguments to DynamoDB objects
#set($locReadings = [])
#foreach($reading in ${ctx.args.locReadings})
    $util.qr($locReadings.add($util.dynamodb.toMapValues($reading)))
#end

{
    "version" : "2018-05-29",
    "operation" : "BatchPutItem",
    "tables" : {
        "locationReadings": $utils.toJson($locReadings),
        "temperatureReadings": $utils.toJson($tempReadings)
    }
}
```

Seperti yang Anda lihat, `BatchPutItem` operasi memungkinkan kita untuk menentukan beberapa tabel.

Mari kita gunakan template pemetaan respons berikut.

 **Templat Pemetaan Respon** 

```
## If there was an error with the invocation
## there might have been partial results
#if($ctx.error)
    ## Append a GraphQL error for that field in the GraphQL response
    $utils.appendError($ctx.error.message, $ctx.error.message)
#end
## Also returns data for the field in the GraphQL response
$utils.toJson($ctx.result.data)
```

Dengan operasi batch, mungkin ada kesalahan dan hasil yang dikembalikan dari pemanggilan. Dalam hal ini, kami bebas melakukan beberapa penanganan kesalahan tambahan.

 **Catatan**: Penggunaan `$utils.appendError()` mirip dengan`$util.error()`, dengan perbedaan utama bahwa itu tidak mengganggu evaluasi template pemetaan. Sebaliknya, itu menandakan ada kesalahan dengan bidang, tetapi memungkinkan template untuk dievaluasi dan akibatnya mengembalikan data kembali ke pemanggil. Kami menyarankan Anda menggunakan `$utils.appendError()` ketika aplikasi Anda perlu mengembalikan sebagian hasil.

Simpan resolver dan navigasikan ke halaman **Kueri** konsol. AWS AppSync Mari kita kirim beberapa pembacaan sensor\$1

Jalankan mutasi berikut:

```
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
    }
  }
}
```

Kami mengirim 10 pembacaan sensor dalam satu mutasi, dengan pembacaan dibagi menjadi dua tabel. ****Gunakan konsol DynamoDB untuk memvalidasi bahwa data muncul di tabel LocationReadings dan TemperatureReadings.****

### BatchDeleteItem - Menghapus Bacaan Sensor
<a name="batchdeleteitem-deleting-sensor-readings"></a>

Demikian pula, kita juga perlu menghapus batch pembacaan sensor. Mari kita gunakan bidang `Mutation.deleteReadings` GraphQL untuk tujuan ini. Pilih **Lampirkan** di sebelah `Mutation.recordReadings` bidang. Pada layar berikutnya, pilih sumber `BatchTutorial` data yang sama yang dibuat di awal tutorial.

Mari kita gunakan template pemetaan permintaan berikut.

 **Templat Pemetaan Permintaan** 

```
## Convert tempReadings arguments to DynamoDB primary keys
#set($tempReadings = [])
#foreach($reading in ${ctx.args.tempReadings})
    #set($pkey = {})
    $util.qr($pkey.put("sensorId", $reading.sensorId))
    $util.qr($pkey.put("timestamp", $reading.timestamp))
    $util.qr($tempReadings.add($util.dynamodb.toMapValues($pkey)))
#end

## Convert locReadings arguments to DynamoDB primary keys
#set($locReadings = [])
#foreach($reading in ${ctx.args.locReadings})
    #set($pkey = {})
    $util.qr($pkey.put("sensorId", $reading.sensorId))
    $util.qr($pkey.put("timestamp", $reading.timestamp))
    $util.qr($locReadings.add($util.dynamodb.toMapValues($pkey)))
#end

{
    "version" : "2018-05-29",
    "operation" : "BatchDeleteItem",
    "tables" : {
        "locationReadings": $utils.toJson($locReadings),
        "temperatureReadings": $utils.toJson($tempReadings)
    }
}
```

Template pemetaan respons sama dengan yang kami gunakan. `Mutation.recordReadings`

 **Templat Pemetaan Respon** 

```
## If there was an error with the invocation
## there might have been partial results
#if($ctx.error)
    ## Append a GraphQL error for that field in the GraphQL response
    $utils.appendError($ctx.error.message, $ctx.error.message)
#end
## Also return data for the field in the GraphQL response
$utils.toJson($ctx.result.data)
```

Simpan resolver dan navigasikan ke halaman **Kueri** konsol. AWS AppSync Sekarang, mari kita hapus beberapa pembacaan sensor\$1

Jalankan mutasi berikut:

```
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
    }
  }
}
```

****Validasi melalui konsol DynamoDB bahwa dua pembacaan ini telah dihapus dari tabel LocationReadings dan TemperatureReadings.****

### BatchGetItem - Ambil Bacaan
<a name="batchgetitem-retrieve-readings"></a>

Operasi umum lainnya untuk aplikasi Kesehatan Hewan Peliharaan kami adalah mengambil pembacaan untuk sensor pada titik waktu tertentu. Mari kita lampirkan resolver ke bidang GraphQL pada `Query.getReadings` skema kita. Pilih **Lampirkan**, dan pada layar berikutnya pilih sumber `BatchTutorial` data yang sama yang dibuat di awal tutorial.

Mari tambahkan template pemetaan permintaan berikut.

 **Templat Pemetaan Permintaan** 

```
## Build a single DynamoDB primary key,
## as both locationReadings and tempReadings tables
## share the same primary key structure
#set($pkey = {})
$util.qr($pkey.put("sensorId", $ctx.args.sensorId))
$util.qr($pkey.put("timestamp", $ctx.args.timestamp))

{
    "version" : "2018-05-29",
    "operation" : "BatchGetItem",
    "tables" : {
        "locationReadings": {
            "keys": [$util.dynamodb.toMapValuesJson($pkey)],
            "consistentRead": true
        },
        "temperatureReadings": {
            "keys": [$util.dynamodb.toMapValuesJson($pkey)],
            "consistentRead": true
        }
    }
}
```

Perhatikan bahwa kita sekarang menggunakan **BatchGetItem**operasi.

Template pemetaan respons kami akan sedikit berbeda karena kami memilih untuk mengembalikan `SensorReading` daftar. Mari kita memetakan hasil pemanggilan ke bentuk yang diinginkan.

 **Templat Pemetaan Respon** 

```
## Merge locationReadings and temperatureReadings
## into a single list
## __typename needed as schema uses an interface
#set($sensorReadings = [])

#foreach($locReading in $ctx.result.data.locationReadings)
    $util.qr($locReading.put("__typename", "LocationReading"))
    $util.qr($sensorReadings.add($locReading))
#end

#foreach($tempReading in $ctx.result.data.temperatureReadings)
    $util.qr($tempReading.put("__typename", "TemperatureReading"))
    $util.qr($sensorReadings.add($tempReading))
#end

$util.toJson($sensorReadings)
```

Simpan resolver dan navigasikan ke halaman **Kueri** konsol. AWS AppSync Sekarang, mari kita ambil pembacaan sensor\$1

Jalankan kueri berikut:

```
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
    }
  }
}
```

Kami telah berhasil mendemonstrasikan penggunaan operasi batch DynamoDB menggunakan. AWS AppSync

## Penanganan Kesalahan
<a name="error-handling"></a>

Dalam AWS AppSync, operasi sumber data terkadang dapat mengembalikan sebagian hasil. Hasil sebagian adalah istilah yang akan kita gunakan untuk menunjukkan ketika output dari suatu operasi terdiri dari beberapa data dan kesalahan. Karena penanganan kesalahan secara inheren spesifik aplikasi, AWS AppSync memberi Anda kesempatan untuk menangani kesalahan dalam template pemetaan respons. Kesalahan pemanggilan resolver, jika ada, tersedia dari konteks sebagai. `$ctx.error` Kesalahan pemanggilan selalu menyertakan pesan dan tipe, dapat diakses sebagai properti `$ctx.error.message` dan. `$ctx.error.type` Selama pemanggilan template pemetaan respons, Anda dapat menangani sebagian hasil dengan tiga cara:

1. menelan kesalahan pemanggilan hanya dengan mengembalikan data

1. meningkatkan kesalahan (menggunakan`$util.error(...)`) dengan menghentikan evaluasi template pemetaan respons, yang tidak akan mengembalikan data apa pun.

1. tambahkan kesalahan (menggunakan`$util.appendError(...)`) dan juga mengembalikan data

Mari kita tunjukkan masing-masing dari tiga poin di atas dengan operasi batch DynamoDB\$1

### Operasi Batch DynamoDB
<a name="dynamodb-batch-operations"></a>

Dengan operasi batch DynamoDB, ada kemungkinan bahwa batch sebagian selesai. Artinya, ada kemungkinan bahwa beberapa item atau kunci yang diminta dibiarkan tidak diproses. Jika AWS AppSync tidak dapat menyelesaikan batch, item yang belum diproses dan kesalahan pemanggilan akan disetel pada konteksnya.

Kami akan menerapkan penanganan kesalahan menggunakan konfigurasi `Query.getReadings` bidang dari `BatchGetItem` operasi dari bagian sebelumnya dari tutorial ini. Kali ini, mari kita berpura-pura bahwa saat mengeksekusi `Query.getReadings` field, tabel DynamoDB `temperatureReadings` kehabisan throughput yang disediakan. DynamoDB mengangkat **ProvisionedThroughputExceededException**a pada upaya kedua AWS AppSync dengan memproses elemen yang tersisa dalam batch.

JSON berikut mewakili konteks serial setelah pemanggilan batch DynamoDB tetapi sebelum template pemetaan respons dievaluasi.

```
{
  "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": []
}
```

Beberapa hal yang perlu diperhatikan pada konteksnya:
+ **kesalahan pemanggilan telah disetel pada konteks di `$ctx.error` by AWS AppSync, dan jenis kesalahan telah disetel ke DynamoDB:. ProvisionedThroughputExceededException**
+ hasil dipetakan per tabel di bawah`$ctx.result.data`, meskipun ada kesalahan
+ kunci yang dibiarkan tidak diproses tersedia di`$ctx.result.data.unprocessedKeys`. Di sini, AWS AppSync tidak dapat mengambil item dengan kunci (sensorid:1, stempel waktu: 2018-02-01T 17:21:05.000 \$1 08:00) karena throughput tabel yang tidak mencukupi.

 **Catatan**: Untuk`BatchPutItem`, itu`$ctx.result.data.unprocessedItems`. Untuk`BatchDeleteItem`, itu`$ctx.result.data.unprocessedKeys`.

Mari kita tangani kesalahan ini dengan tiga cara berbeda.

#### 1. Menelan kesalahan pemanggilan
<a name="swallowing-the-invocation-error"></a>

Mengembalikan data tanpa menangani kesalahan pemanggilan secara efektif menelan kesalahan, membuat hasil untuk bidang GraphQL yang diberikan selalu berhasil.

Template pemetaan respons yang kita tulis sudah tidak asing lagi dan hanya berfokus pada data hasil.

Templat pemetaan respons:

```
$util.toJson($ctx.result.data)
```

Tanggapan GraphQL:

```
{
  "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
      }
    ]
  }
}
```

Tidak ada kesalahan yang akan ditambahkan ke respons kesalahan karena hanya data yang ditindaklanjuti.

#### 2. Memunculkan kesalahan untuk membatalkan eksekusi template
<a name="raising-an-error-to-abort-the-template-execution"></a>

Ketika kegagalan sebagian harus diperlakukan sebagai kegagalan total dari perspektif klien, Anda dapat membatalkan eksekusi template untuk mencegah pengembalian data. Metode `$util.error(...)` utilitas mencapai perilaku ini dengan tepat.

Templat pemetaan respons:

```
## there was an error let's mark the entire field
## as failed and do not return any data back in the response
#if ($ctx.error)
    $util.error($ctx.error.message, $ctx.error.type, null, $ctx.result.data.unprocessedKeys)
#end

$util.toJson($ctx.result.data)
```

Tanggapan GraphQL:

```
{
  "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. (...)"
    }
  ]
}
```

*Meskipun beberapa hasil mungkin telah dikembalikan dari operasi batch DynamoDB, kami memilih untuk memunculkan kesalahan sehingga bidang `getReadings` GraphQL adalah nol dan kesalahan telah ditambahkan ke blok kesalahan respons GraphQL.*

#### 3. Menambahkan kesalahan untuk mengembalikan data dan kesalahan
<a name="appending-an-error-to-return-both-data-and-errors"></a>

Dalam kasus tertentu, untuk memberikan pengalaman pengguna yang lebih baik, aplikasi dapat mengembalikan sebagian hasil dan memberi tahu klien mereka tentang item yang belum diproses. Klien dapat memutuskan untuk menerapkan coba lagi atau menerjemahkan kesalahan kembali ke pengguna akhir. Ini `$util.appendError(...)` adalah metode utilitas yang memungkinkan perilaku ini dengan membiarkan desainer aplikasi menambahkan kesalahan pada konteks tanpa mengganggu evaluasi template. Setelah mengevaluasi template, AWS AppSync akan memproses kesalahan konteks apa pun dengan menambahkannya ke blok kesalahan respons GraphQL.

Templat pemetaan respons:

```
#if ($ctx.error)
    ## pass the unprocessed keys back to the caller via the `errorInfo` field
    $util.appendError($ctx.error.message, $ctx.error.type, null, $ctx.result.data.unprocessedKeys)
#end

$util.toJson($ctx.result.data)
```

Kami meneruskan kesalahan pemanggilan dan elemen UnprocessedKeys di dalam blok kesalahan respons GraphQL. `getReadings`Bidang ini juga mengembalikan sebagian data dari tabel **LocationReadings** seperti yang Anda lihat pada respons di bawah ini.

Tanggapan GraphQL:

```
{
  "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. (...)"
    }
  ]
}
```