

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# Amazon AppSync 解析器映射模板更新日志
解析器映射模板更改日志

**注意**  
我们现在主要支持 APPSYNC\$1JS 运行时系统及其文档。请考虑使用 APPSYNC\$1JS 运行时系统和[此处](https://docs.amazonaws.cn/appsync/latest/devguide/resolver-reference-js-version.html)的指南。

解析器和函数映射模板已版本化。映射模板版本（例如 `2018-05-29`）指示以下内容：
+ 请求模板提供的数据来源请求配置的预期形状
+ 请求映射模板和响应映射模板的执行行为

版本使用 YYYY-MM-DD格式表示，较晚的日期对应于较新的版本。该页面列出了 Amazon AppSync中当前支持的映射模板版本之间的差异。

**Topics**
+ [

## 每个版本矩阵的数据来源操作可用性
](#aws-appsync-resolver-mapping-template-operation-availability-per-version)
+ [

## 更改单位解析器映射模板上的版本
](#changing-the-version-on-a-unit-resolver-mapping-template)
+ [

## 更改函数上的版本
](#changing-the-version-on-a-function)
+ [

## 2018-05-29
](#aws-appsync-resolver-mapping-template-version-2018-05-29)
+ [

## 2017-02-28
](#aws-appsync-resolver-mapping-template-version-2017-02-28)

## 每个版本矩阵的数据来源操作可用性



| 支持的操作/版本 | 2017-02-28 | 2018-05-29 | 
| --- | --- | --- | 
|  Amazon Lambda 调用  |  支持  |  是  | 
|  Amazon Lambda BatchInvoke  |  是  |  是  | 
|  None Datasource  |  支持  |  是  | 
|  Amazon OpenSearch GET  |  支持  |  是  | 
|  Amazon OpenSearch POST  |  支持  |  是  | 
|  亚马逊 P OpenSearch UT  |  支持  |  是  | 
|  亚马逊 OpenSearch 删除  |  支持  |  是  | 
|  Amazon OpenSearch GET  |  支持  |  是  | 
|  DynamoDB GetItem  |  支持  |  是  | 
|  DynamoDB Scan  |  支持  |  是  | 
|  DynamoDB Query  |  支持  |  是  | 
|  DynamoDB DeleteItem  |  支持  |  是  | 
|  DynamoDB PutItem  |  支持  |  是  | 
|  DynamoDB BatchGetItem  |  否  |  是  | 
|  DynamoDB BatchPutItem  |  否  |  是  | 
|  DynamoDB BatchDeleteItem  |  否  |  是  | 
|  HTTP  |  否  |  是  | 
|  Amazon RDS  |  否  |  是  | 

 **注**：函数中目前仅支持 **2018-05-29** 版本。

## 更改单位解析器映射模板上的版本


对于单位解析器，将版本指定为请求映射模板正文的一部分。要更新版本，只需将 `version` 字段更新为新版本。

例如，要更新 Amazon Lambda 模板上的版本，请执行以下操作：

```
{
    "version": "2017-02-28",
    "operation": "Invoke",
    "payload": {
        "field": "getPost",
        "arguments": $utils.toJson($context.arguments)
    }
}
```

您需要将版本字段从 `2017-02-28` 更新为 `2018-05-29`，如下所示：

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

## 更改函数上的版本


对于函数，将版本指定为函数对象上的 `functionVersion` 字段。要更新版本，只需更新 `functionVersion`。*注意：*目前，函数仅支持 `2018-05-29`。

以下是用于更新现有函数版本的 CLI 命令的示例：

```
aws appsync update-function \
--api-id REPLACE_WITH_API_ID \
--function-id REPLACE_WITH_FUNCTION_ID \
--data-source-name "PostTable" \
--function-version "2018-05-29" \
--request-mapping-template "{...}" \
--response-mapping-template "\$util.toJson(\$ctx.result)"
```

 **注意：**建议从函数请求映射模板中省略版本字段，因为它不会被接受。如果您在函数请求映射模板中指定了一个版本，则该版本值将由 `functionVersion` 字段的值覆盖。

## 2018-05-29


### 行为更改

+ 如果数据来源调用结果为 `null`，则执行响应映射模板。
+ 如果数据来源调用产生了错误，现在由您来处理该错误，响应映射模板评估结果将**始终**放置在 GraphQL 响应 `data` 块中。

### Reasoning

+ `null` 调用结果具有意义，在某些应用程序使用案例中，我们可能希望以自定义方式处理 `null` 结果。例如，应用程序可能会检查 Amazon DynamoDB 表中是否存在记录以执行某些授权检查。在这种情况下，`null` 调用结果意味着用户可能未获得授权。现在，执行响应映射模板可以引发未经授权的错误。此行为向 API 设计器提供了更大的控制。

给定以下响应映射模板：

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

之前使用 `2017-02-28`，如果 `$ctx.result` 返回 null，则未执行响应映射模板。利用 `2018-05-29`，我们现在可以处理这种情况。例如，我们可以选择引发授权错误，如下所示：

```
# throw an unauthorized error if the result is null
#if ( $util.isNull($ctx.result) )
    $util.unauthorized()
#end
$util.toJson($ctx.result)
```

 **注：**从数据来源返回的错误有时并不是致命的，或者甚至是预期的，这就是应向响应映射模板提供处理调用错误并决定是否忽略它、重新引发它或引发不同的错误的灵活性。

给定以下响应映射模板：

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

以前，使用 `2017-02-28`，如果出现调用错误，则会评估响应映射模板，并自动将结果放入 GraphQL 响应的 `errors` 块中。利用 `2018-05-29`，我们现在可以选择如何处理错误，重新引发错误、引发不同的错误，或者在返回数据时追加错误。

### 重新引发调用错误


在以下响应模板中，我们引发了从数据来源返回的同一错误。

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

如果出现调用错误（例如，出现 `$ctx.error`），则响应如下所示：

```
{
    "data": {
        "getPost": null
    },
    "errors": [
        {
            "path": [
                "getPost"
            ],
            "errorType": "DynamoDB:ConditionalCheckFailedException",
            "message": "Conditional check failed exception...",
            "locations": [
                {
                    "line": 5,
                    "column": 5
                }
            ]
        }
    ]
}
```

### 引发不同的错误


在以下响应模板中，我们在处理从数据来源返回的错误之后引发了自己的自定义错误。

```
#if ( $ctx.error )
    #if ( $ctx.error.type.equals("ConditionalCheckFailedException") )
        ## we choose here to change the type and message of the error for ConditionalCheckFailedExceptions
        $util.error("Error while updating the post, try again. Error: $ctx.error.message", "UpdateError")
    #else
        $util.error($ctx.error.message, $ctx.error.type)
    #end
#end
$util.toJson($ctx.result)
```

如果出现调用错误（例如，出现 `$ctx.error`），则响应如下所示：

```
{
    "data": {
        "getPost": null
    },
    "errors": [
        {
            "path": [
                "getPost"
            ],
            "errorType": "UpdateError",
            "message": "Error while updating the post, try again. Error: Conditional check failed exception...",
            "locations": [
                {
                    "line": 5,
                    "column": 5
                }
            ]
        }
    ]
}
```

### 追加错误以返回数据


在以下响应模板中，我们追加从数据来源返回的同一错误，同时将数据返回到响应中。这也称为部分响应。

```
#if ( $ctx.error )
    $util.appendError($ctx.error.message, $ctx.error.type)
    #set($defaultPost = {id: "1", title: 'default post'})
    $util.toJson($defaultPost)
#else
    $util.toJson($ctx.result)
#end
```

如果出现调用错误（例如，出现 `$ctx.error`），则响应如下所示：

```
{
    "data": {
        "getPost": {
            "id": "1",
            "title: "A post"
        }
    },
    "errors": [
        {
            "path": [
                "getPost"
            ],
            "errorType": "ConditionalCheckFailedException",
            "message": "Conditional check failed exception...",
            "locations": [
                {
                    "line": 5,
                    "column": 5
                }
            ]
        }
    ]
}
```

#### 从 *2017-02-28* 迁移到 *2018-05-29*


从 **2017-02-28** 迁移到 **2018-05-29** 非常简单。更改解析器请求映射模板或函数版本对象上的版本字段。但请注意，**2018-05-29** 执行的行为与 **2017-02-28** 的不同，[此处](#aws-appsync-resolver-mapping-template-version-2018-05-29)概述了更改。

#### 从 *2017-02-28* 到 *2018-05-29* 保留相同的执行行为


在某些情况下，在执行 **2018-05-29** 版本的模板时，可以保留与 **2017-02-28** 版本相同的执行行为。

### 示例：DynamoDB PutItem


鉴于以下 **2017-02-28** DynamoDB 请求模板 PutItem：

```
{
    "version" : "2017-02-28",
    "operation" : "PutItem",
    "key": {
        "foo" : ... typed value,
        "bar" : ... typed value
    },
    "attributeValues" : {
        "baz" : ... typed value
    },
    "condition" : {
       ...
    }
}
```

以及以下响应模板：

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

迁移到 **2018-05-29** 会更改这些模板，如下所示：

```
{
    "version" : "2018-05-29", ## Note the new 2018-05-29 version
    "operation" : "PutItem",
    "key": {
        "foo" : ... typed value,
        "bar" : ... typed value
    },
    "attributeValues" : {
        "baz" : ... typed value
    },
    "condition" : {
       ...
    }
}
```

更改响应模板，如下所示：

```
## If there is a datasource invocation error, we choose to raise the same error
## the field data will be set to null.
#if($ctx.error)
  $util.error($ctx.error.message, $ctx.error.type, $ctx.result)
#end

## If the data source invocation is null, we return null.
#if($util.isNull($ctx.result))
  #return
#end

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

现在，您有责任处理错误，我们选择使用从 DynamoDB 返回的 `$util.error()` 来引发同一错误。您可以调整此代码段以将映射模板转换为 **2018-05-29**，请注意，如果您的响应模板不同，则必须考虑执行行为更改。

### 示例：DynamoDB GetItem


鉴于以下 **2017-02-28** DynamoDB 请求模板 GetItem：

```
{
    "version" : "2017-02-28",
    "operation" : "GetItem",
    "key" : {
        "foo" : ... typed value,
        "bar" : ... typed value
    },
    "consistentRead" : true
}
```

以及以下响应模板：

```
## map table attribute postId to field Post.id
$util.qr($ctx.result.put("id", $ctx.result.get("postId")))

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

迁移到 **2018-05-29** 会更改这些模板，如下所示：

```
{
    "version" : "2018-05-29", ## Note the new 2018-05-29 version
    "operation" : "GetItem",
    "key" : {
        "foo" : ... typed value,
        "bar" : ... typed value
    },
    "consistentRead" : true
}
```

更改响应模板，如下所示：

```
## If there is a datasource invocation error, we choose to raise the same error
#if($ctx.error)
  $util.error($ctx.error.message, $ctx.error.type)
#end

## If the data source invocation is null, we return null.
#if($util.isNull($ctx.result))
  #return
#end

## map table attribute postId to field Post.id
$util.qr($ctx.result.put("id", $ctx.result.get("postId")))

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

在 **2017-02-28** 版本中，如果数据来源调用是 `null`，则表示 DynamoDB 表中没有与我们的键匹配的项目，响应映射模板将不会执行。在大多数情况下，这都是可行的，但如果您期望 `$ctx.result` 不是 `null`，则现在必须处理该情况。

## 2017-02-28


### 特性

+ 如果数据来源调用结果为 `null`，则**不会**执行响应映射模板。
+ 如果数据来源调用产生了错误，则将执行响应映射模板，并将评估结果放入 GraphQL 响应 `errors.data` 块中。