

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# Lambda の AWS AppSync リゾルバーマッピングテンプレートリファレンス
<a name="resolver-mapping-template-reference-lambda"></a>

**注記**  
現在、主に APPSYNC\$1JS ランタイムとそのドキュメントをサポートしています。[こちら](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html) で APPSYNC\$1JS ランタイムとそのガイドの使用をご検討ください。

 AWS AppSync 関数とリゾルバーを使用して、 アカウントにある Lambda 関数を呼び出すことができます。クライアントに返す前に、リクエストペイロードと Lambda 関数からのレスポンスを調整することができます。マッピングテンプレートを使用して、呼び出されるオペレーションの特性に関して、 AWS AppSync にヒントを渡すこともできます。このセクションでは、サポートされる Lambda 操作用の異なるマッピングテンプレートについて説明します。

## リクエストマッピングテンプレート
<a name="request-mapping-template"></a>

Lambda リクエストマッピングテンプレートは、Lambda 関数に関連するフィールドを処理します。

```
{
  "version": string,
  "operation": Invoke|BatchInvoke,
  "payload": any type,
  "invocationType": RequestResponse|Event
}
```

これは、解決時の Lambda リクエストマッピングテンプレートの JSON スキーマ表現です。

```
{
  "definitions": {},
  "$schema": "https://json-schema.org/draft-06/schema#",
  "$id": "https://aws.amazon.com/appsync/request-mapping-template.json",
  "type": "object",
  "properties": {
    "version": {
      "$id": "/properties/version",
      "type": "string",
      "enum": [
        "2018-05-29"
      ],
      "title": "The Mapping template version.",
      "default": "2018-05-29"
    },
    "operation": {
      "$id": "/properties/operation",
      "type": "string",
      "enum": [
        "Invoke",
        "BatchInvoke"
      ],
      "title": "The Mapping template operation.",
      "description": "What operation to execute.",
      "default": "Invoke"
    },
    "payload": {},
    "invocationType": {
      "$id": "/properties/invocationType",
      "type": "string",
      "enum": [
        "RequestResponse",
        "Event"
      ],
      "title": "The Mapping template invocation type.",
      "description": "What invocation type to execute.",
      "default": "RequestResponse"
    }
  },
  "required": [
    "version",
    "operation"
  ],
  "additionalProperties": false
}
```

以下は、ペイロードデータが GraphQL スキーマの `getPost` フィールドであり、コンテキストの引数を含む `invoke` オペレーションを使用する例です。

```
{
  "version": "2018-05-29",
  "operation": "Invoke",
  "payload": {
    "field": "getPost",
    "arguments": $util.toJson($context.arguments)
  }
}
```

マッピングドキュメント全体は、使用する Lambda 関数に入力として渡されます。これにより、先ほどのサンプルは以下のようになります。

```
{
  "version": "2018-05-29",
  "operation": "Invoke",
  "payload": {
    "field": "getPost",
    "arguments": {
      "id": "postId1"
    }
  }
}
```

### バージョン
<a name="version"></a>

すべてのリクエストマッピングテンプレートに共通で、`version` はテンプレートが使用するバージョンを定義します。`version` は必須で、静的値です。

```
"version": "2018-05-29"
```

### 運用
<a name="operation"></a>

Lambda データソースでは、`operation` フィールドで 2 つのオペレーションである `Invoke` と `BatchInvoke` を定義できます。`Invoke` オペレーションは、GraphQL フィールドリゾルバーごとに Lambda 関数を呼び出すことを AWS AppSync に知らせます。 `BatchInvoke` は、現在の GraphQL フィールドのリクエストをバッチ処理するように AWS AppSync に指示します。`operation` フィールドは必須です。

`Invoke` では、解決されたリクエストマッピングテンプレートは Lambda 関数の入力ペイロードと一致します。上記の例を変更してみましょう。

```
{
  "version": "2018-05-29",
  "operation": "Invoke",
    "payload": {
      "arguments": $util.toJson($context.arguments)
    }
}
```

これは解決され、Lambda 関数に渡されます。この関数は次のようになります。

```
{
  "version": "2018-05-29",
  "operation": "Invoke",
    "payload": {
      "arguments": {
        "id": "postId1"
      }
    }
}
```

`BatchInvoke` では、バッチ内のすべてのフィールドリゾルバーにマッピングテンプレートが適用されます。簡潔にするために、 AWS AppSync は解決されたすべてのマッピングテンプレート`payload`値を、マッピングテンプレートに一致する 1 つのオブジェクトのリストにマージします。次のサンプルテンプレートは、マージを示します。

```
{
  "version": "2018-05-29",
  "operation": "BatchInvoke",
  "payload": $util.toJson($context)
}
```

このテンプレートは、次のマッピングドキュメントに解決されます。

```
{
  "version": "2018-05-29",
  "operation": "BatchInvoke",
  "payload": [
    {...}, // context for batch item 1
    {...}, // context for batch item 2
    {...}  // context for batch item 3
  ]
}
```

`payload` リストの各要素は、1 回のバッチ項目に対応しています。また、Lambda 関数はリスト形式のレスポンスを返すことが予期され、次のように、各項目はリクエストで送信された順序になります。

```
[
  { "data": {...}, "errorMessage": null, "errorType": null }, // result for batch item 1
  { "data": {...}, "errorMessage": null, "errorType": null }, // result for batch item 2
  { "data": {...}, "errorMessage": null, "errorType": null }  // result for batch item 3
]
```

### ペイロード
<a name="payload"></a>

`payload` フィールドは、任意の正しい形式の JSON を Lambda 関数に渡す際に使用するコンテナです。`operation` フィールドが に設定されている場合`BatchInvoke`、 AWS AppSync は既存の`payload`値をリストにラップします。`payload` フィールドはオプションです。

### 呼び出しタイプ
<a name="async-invocation-type"></a>

Lambda データソースでは、2 つの呼び出しタイプ `RequestResponse` と `Event` を定義できます。呼び出しタイプは、[Lambda API](https://docs.aws.amazon.com//lambda/latest/api/API_Invoke.html) で定義されている呼び出しタイプと同義です。`RequestResponse` 呼び出しタイプ lets AWS AppSync は Lambda 関数を同期的に呼び出してレスポンスを待ちます。`Event` 呼び出しにより、Lambda 関数を非同期的に呼び出すことができます。Lambda が `Event` 呼び出しタイプのリクエストを処理する方法の詳細については、「[非同期呼び出し](https://docs.aws.amazon.com/lambda/latest/dg/invocation-async.html)」を参照してください。`invocationType` フィールドはオプションです。このフィールドがリクエストに含まれていない場合、 AWS AppSync はデフォルトで`RequestResponse`呼び出しタイプになります。

`invocationType` フィールドでは、解決されたリクエストは Lambda 関数の入力ペイロードと一致します。上記の例を変更してみましょう。

```
{
  "version": "2018-05-29",
  "operation": "Invoke",
  "invocationType": "Event"
  "payload": {
    "arguments": $util.toJson($context.arguments)
  }
}
```

これは解決され、Lambda 関数に渡されます。この関数は次のようになります。

```
{
  "version": "2018-05-29",
  "operation": "Invoke",
  "invocationType": "Event",
  "payload": {
    "arguments": {
      "id": "postId1"
    }
  }
}
```

`BatchInvoke` オペレーションを`Event`呼び出しタイプフィールドと組み合わせて使用すると、 AWS AppSync は上記の同じ方法でフィールドリゾルバーをマージし、リクエストは を値`payload`のリストとする非同期イベントとして Lambda 関数に渡されます。`Event` 呼び出しタイプのリゾルバーのリゾルバーキャッシュは、キャッシュヒットがあった場合に Lambda に送信されないため、無効にすることをお勧めします。

## レスポンスマッピングテンプレート
<a name="response-mapping-template"></a>

他のデータソースと同様に、Lambda 関数は GraphQL タイプに変換する必要があるレスポンスを AWS AppSync に送信します。

Lambda 関数の結果は、Velocity Template Language (VTL) `$context.result` プロパティを通じて使用できる `context` オブジェクトで設定されます。

Lambda 関数のレスポンスの形状と GraphQL タイプの形状が正確に一致する場合は、以下のレスポンスマッピングテンプレートを使用して、レスポンスを転送できます。

```
$util.toJson($context.result)
```

レスポンスマッピングテンプレートに適用される形状の制限や必須フィールドはありません。ただし、GraphQL が厳密に型指定されているので、解決されたマッピングテンプレートは予想される GraphQL タイプに一致する必要があります。

## Lambda 関数のバッチ処理されたレスポンス
<a name="aws-appsync-resolver-mapping-template-reference-lambda-batched-response"></a>

`operation` フィールドが に設定されている場合`BatchInvoke`、 AWS AppSync は Lambda 関数から返される項目のリストを想定します。 AWS AppSync が各結果を元のリクエスト項目にマッピングするには、レスポンスリストのサイズと順序が一致している必要があります。レスポンスリストに `null` 項目がある場合も有効です。その場合、`$ctx.result` が *null* に設定されます。

## ダイレクトLambda リゾルバー
<a name="direct-lambda-resolvers"></a>

マッピングテンプレートの使用を完全に回避する場合、 AWS AppSync は Lambda 関数にデフォルトのペイロードを提供し、GraphQL タイプにデフォルトの Lambda 関数レスポンスを提供できます。リクエストテンプレートを提供するか、レスポンステンプレートを提供するか、どちらも提供しないかを選択できます。 AWS AppSync はそれに応じて処理します。

### ダイレクト Lambda リクエストマッピングテンプレート
<a name="lambda-mapping-template-bypass-request"></a>

リクエストマッピングテンプレートが指定されていない場合、 AWS AppSync は `Invoke`オペレーションとして Lambda 関数に直接`Context`オブジェクトを送信します。`Context` オブジェクトの構造の詳細については、「[AWS AppSync リゾルバーマッピングテンプレートコンテキストリファレンス](resolver-context-reference.md)」を参照してください。

### ダイレクト Lambda レスポンスマッピングテンプレート
<a name="lambda-mapping-template-bypass-response"></a>

レスポンスマッピングテンプレートが指定されていない場合、 AWS AppSync は Lambda 関数のレスポンスを受信したときに 2 つの処理のいずれかを実行します。リクエストマッピングテンプレートを指定しなかった場合、またはバージョン `2018-05-29` でリクエストマッピングテンプレートを提供した場合、応答は次のレスポンスマッピングテンプレートと同様になります。

```
#if($ctx.error)
     $util.error($ctx.error.message, $ctx.error.type, $ctx.result)
 #end
 $util.toJson($ctx.result)
```

バージョン `2017-02-28` のテンプレートを提供した場合、レスポンスロジックは次のレスポンスマッピングテンプレートと同様に機能します。

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

表面的には、マッピングテンプレートのバイパスは、前の例に示すように、特定のマッピングテンプレートを使用する場合と同様に機能します。ただし、裏では、マッピングテンプレートの評価は完全に回避されます。テンプレート評価ステップはバイパスされるため、一部のシナリオでは、評価が必要なレスポンスマッピングテンプレートを持つ Lambda 関数と比較して、アプリケーションのレスポンスのオーバーヘッドとレイテンシーが少なくなる場合があります。

### ダイレクト Lambda リゾルバーレスポンスのカスタムエラー処理
<a name="lambda-mapping-template-bypass-errors"></a>

カスタム例外を発生させることにより、ダイレクト Lambda リゾルバーによって呼び出される Lambda 関数からのエラーレスポンスをカスタマイズできます。次の例では、JavaScript を使用してカスタム例外を作成する方法を示します。

```
class CustomException extends Error {
  constructor(message) {
    super(message);
    this.name = "CustomException";
  }
}
 
throw new CustomException("Custom message");
```

例外が発生すると、`errorType` と `errorMessage` が、それぞれ個別に、スローされるカスタムエラーの `name` と `message` になります。

`errorType` が の場合`UnauthorizedException`、 AWS AppSync はカスタムメッセージの代わりにデフォルトのメッセージ (`"You are not authorized to make this call."`) を返します。

以下のスニペットは、カスタム `errorType` を示す GraphQL レスポンスの例です。

```
{
  "data": {
    "query": null
  },
  "errors": [
    {
      "path": [
        "query"
      ],
      "data": null,
      "errorType": "CustomException",
      "errorInfo": null,
      "locations": [
        {
          "line": 5,
          "column": 10,
          "sourceName": null
        }
      ],
      "message": "Custom Message"
    }
  ]
}
```

### ダイレクト Lambda リゾルバー: バッチ処理が有効
<a name="lambda-resolvers-batching"></a>

Direct Lambda リゾルバーのバッチ処理を有効にするには、リゾルバーで `maxBatchSize` を設定します。`maxBatchSize` をダイレクト Lambda リゾルバーで `0` より大きい値に設定すると、 AWS AppSync は Lambda 関数に最大サイズ `maxBatchSize` のリクエストをバッチで送信します。

ダイレクト Lambda リゾルバーで `maxBatchSize` を `0` に設定すると、バッチ処理がオフになります。

Lambda リゾルバーによるバッチ処理の仕組みの詳細については、「[高度なユースケース: バッチ処理](tutorial-lambda-resolvers.md#advanced-use-case-batching)」を参照してください。

#### リクエストマッピングテンプレート
<a name="lambda-resolvers-batching-request-template"></a>

バッチ処理が有効で、リクエストマッピングテンプレートが提供されていない場合、 AWS AppSync は、`Context` オブジェクトのリストを `BatchInvoke` 操作として Lambda 関数に直接送信します。

#### レスポンスマッピングテンプレート
<a name="lambda-resolvers-batching-response-template"></a>

バッチ処理が有効で、レスポンスマッピングテンプレートが提供されていない場合、レスポンスロジックは次のレスポンスマッピングテンプレートと同様に機能します。

```
#if( $context.result && $context.result.errorMessage )
      $utils.error($context.result.errorMessage, $context.result.errorType,
      $context.result.data)
#else
      $utils.toJson($context.result.data)
#end
```

Lambda 関数は、送信された `Context` オブジェクトのリストと同じ順序で結果のリストを返す必要があります。特定の結果に対して `errorMessage` と `errorType`を指定することで、個々のエラーを返すことができます。リストの各結果には、次の形式があります。

```
{
   "data" : { ... }, // your data
   "errorMessage" : { ... }, // optional, if included an error entry is added to the "errors" object in the AppSync response 
   "errorType" : { ... } // optional, the error type
}
```

**注記**  
結果オブジェクトの他のフィールドは現時点では無視されます。

#### Lambda からのエラーの処理
<a name="lambda-resolvers-batching-error-handling"></a>

Lambda 関数に例外またはエラーを投げると、すべての結果に対してエラーを返すことができます。バッチリクエストのペイロードリクエストまたはレスポンスサイズが大きすぎる場合、Lambda はエラーを返します。その場合は、`maxBatchSize` を小さくするか、レスポンスペイロードのサイズを小さくすることを検討してください。

個別のエラー処理については、「[個々のエラーを返す](tutorial-lambda-resolvers.md#returning-individual-errors)」を参照してください。

#### サンプル Lambda 関数
<a name="sample-lambda-function"></a>

以下のスキーマを使用して、`Post.relatedPosts` フィールドリゾルバー用のダイレクト Lambda リゾルバーを作成し、`maxBatchSize` を `0` を超える値に設定することでバッチ処理を有効にできます。

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

type Query {
    getPost(id:ID!): Post
    allPosts: [Post]
}

type Mutation {
    addPost(id: ID!, author: String!, title: String, content: String, url: String): Post!
}

type Post {
    id: ID!
    author: String!
    title: String
    content: String
    url: String
    ups: Int
    downs: Int
    relatedPosts: [Post]
}
```

次のクエリでは、`relatedPosts` を解決するリクエストのバッチとともに Lambda 関数が呼び出されます。

```
query getAllPosts {
  allPosts {
    id
    relatedPosts {
      id
    }
  }
}
```

Lambda 関数の簡単な実装を以下に示します。

```
const posts = {
  1: {
    id: '1',
    title: 'First book',
    author: 'Author1',
    url: 'https://amazon.com/',
    content:
      'SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1',
    ups: '100',
    downs: '10',
  },
  2: {
    id: '2',
    title: 'Second book',
    author: 'Author2',
    url: 'https://amazon.com',
    content: 'SAMPLE TEXT AUTHOR 2 SAMPLE TEXT AUTHOR 2 SAMPLE TEXT',
    ups: '100',
    downs: '10',
  },
  3: { id: '3', title: 'Third book', author: 'Author3', url: null, content: null, ups: null, downs: null },
  4: {
    id: '4',
    title: 'Fourth book',
    author: 'Author4',
    url: 'https://www.amazon.com/',
    content:
      'SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4',
    ups: '1000',
    downs: '0',
  },
  5: {
    id: '5',
    title: 'Fifth book',
    author: 'Author5',
    url: 'https://www.amazon.com/',
    content: 'SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT',
    ups: '50',
    downs: '0',
  },
}

const relatedPosts = {
  1: [posts['4']],
  2: [posts['3'], posts['5']],
  3: [posts['2'], posts['1']],
  4: [posts['2'], posts['1']],
  5: [],
}
exports.handler = async (event) => {
  console.log('event ->', event)
  // retrieve the ID of each post
  const ids = event.map((context) => context.source.id)
  // fetch the related posts for each post id
  const related = ids.map((id) => relatedPosts[id])

  // return the related posts; or an error if none were found
  return related.map((r) => {
    if (r.length > 0) {
      return { data: r }
    } else {
      return { data: null, errorMessage: 'Not found', errorType: 'ERROR' }
    }
  })
}
```