本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
解析器映射模板概述
Amazon AppSync 允许您通过对资源执行操作来响应 GraphQL 请求。对于要运行查询或变更的每个 GraphQL 字段,必须连接解析器才能与数据源通信。通信通常通过数据源特有的参数或操作进行。
解析器是 GraphQL 和数据源之间的连接器。它们讲述了Amazon AppSync 如何将传入的 GraphQL 请求转换为后端数据源的指令,以及如何将来自该数据源的响应转换回 GraphQL 响应。它们以 Apache Velocity 模板语言 (VTL)
其中有两种类型的解析器以略Amazon AppSync 有不同的方式利用映射模板:
-
单位解析器
-
管道解析器
单位解析器
单元解析器是独立实体,仅包含请求和响应模板。将它们用于简单、单一的操作(例如,列出来自单个数据源的项目)。
-
请求模板:在解析 GraphQL 操作后获取传入请求,并将其转换为所选数据源操作的请求配置。
-
响应模板:解释来自数据源的响应并将其映射到 GraphQL 字段输出类型的形状。
管道解析器
管道解析器包含一个或多个按顺序执行的函数。每个函数都包含请求模板和响应模板。管道解析器还具有一个之前模板和一个之后模板,它们围绕着模板包含的一系列函数。之后的模板映射到 GraphQL 字段输出类型。管道解析器与单位解析器的不同之处在于响应模板映射输出的方式。管道解析器可以映射到您想要的任何输出,包括另一个函数的输入或管道解析器的后续模板。
管道解析器函数使您能够编写通用逻辑,可以在架构中的多个解析器中重复使用这些逻辑。函数直接附加到数据源,与单元解析器一样,包含相同的请求和响应映射模板格式。
下图显示了左侧的单元解析器和右侧的管道解析器的处理流程。

管道解析器包含单元解析器支持的超集功能,还有更多,但代价是复杂性稍微高一些。
管道解析程序剖析
管道解析器由 Bef or e 映射模板、Af ter 映射模板和函数列表组成。每个函数都有一个针对数据源执行的请求和响应映射模板。由于管道解析程序将执行委托给函数列表,因此它不会链接到任何数据源。单元解析程序和函数是对数据源执行操作的基元。有关更多信息,请参阅 Resolver 映射模板概述。
映射模板之前
管道解析器的请求映射模板或 Before 步骤允许您在执行定义的函数之前执行一些准备逻辑。
函数列表
管道解析程序将按顺序运行的函数的列表。管道解析程序请求映射模板评估的结果可供第一个函数用作 $ctx.prev.result
。每个函数输出可供下一个函数用作 $ctx.prev.result
。
之后映射模板
管道解析器的响应映射模板或 Af ter 步骤允许您执行从最后一个函数的输出到预期的 GraphQL 字段类型的最终映射逻辑。函数列表中最后一个函数的输出可在管道解析程序映射模板中用作 $ctx.prev.result
或 $ctx.result
。
执行流程
给定一个由两个函数组成的管道解析器,下面的列表表示调用该解析器时的执行流程:

-
管道解析器在映射模板之前
-
函数 1:函数请求映射模板
-
函数 1:数据源调用
-
函数 1:函数响应映射模板
-
函数 2:函数请求映射模板
-
函数 2:数据源调用
-
函数 2:函数响应映射模板
-
管道解析器映射模板之后
管道解析程序执行流是单向的,并在解析程序上静态定义。
有用的 Apache Velocity 模板语言 (VTL) 实用程序
随着应用程序复杂性的增加,VTL 实用工具和指令在这里有助于提高开发效率。在使用管道解析程序时,以下实用工具可为您提供帮助。
$ctx.stash
存储库是在Map
每个解析器和函数映射模板中提供的。同一存储实例通过单个解析程序生效。这意味着您可以使用存储来跨请求和响应映射模板以及管道解析程序中的函数传递任意数据。该存储库公开了与 Java 地图
$ctx.prev.result
$ctx.prev.result
代表先前在管道解析器中执行的操作的结果。
如果先前的操作是管道解析器的 Before 映射模板,则$ctx.prev.result
表示模板评估的输出,可供管道中的第一个函数使用。如果上一个操作是第一个函数,则 $ctx.prev.result
表示第一个函数的输出,并且可供管道中的第二个函数使用。如果前一个操作是最后一个函数,则$ctx.prev.result
表示最后一个函数的输出,并可供管道解析器的 After 映射模板使用。
#return(data: Object)
如果您需要从任何映射模板提前返回,#return(data: Object)
指令会很有用。#return(data: Object)
类似于编程语言中的 return 关键字,因为它会从最近的逻辑范围块返回。这意味着在解析程序映射模板中使用 #return
会从解析程序返回。在解析程序映射模板中使用 #return(data: Object)
会在 GraphQL 字段上设置 data
。此外,从函数映射模板使用 #return(data: Object)
会从函数返回,并继续执行到管道中的下一个函数或解析程序响应映射模板。
#return
这与相同#return(data:
Object)
,但null
将改为返回。
$util.error
$util.error
实用工具对于引发字段错误很有用。在函数映射模板中使用 $util.error
会立即引发字段错误,从而阻止执行后续函数。有关更多详细信息和其他$util.error
签名,请访问 Resolver 映射模板实用程序参考资料。
$util.appendError
$util.appendError
类似于 $util.error()
,主要区别在于前者不会中断映射模板的评估。相反,它指示该字段存在错误,但允许评估模板并因此会返回数据。在函数中使用 $util.appendError
将不会中断管道的执行流。有关更多详细信息和其他$util.error
签名,请访问 Resolver 映射模板实用程序参考资料。
示例 模板
假设您有一个 DynamoDB 数据源和一个名为的字段的 Unit 解析器getPost(id:ID!)
,该字段使用以下 GraphQL 查询返回Post
类型:
getPost(id:1){ id title content }
解析程序模板应如下所示:
{ "version" : "2018-05-29", "operation" : "GetItem", "key" : { "id" : $util.dynamodb.toDynamoDBJson($ctx.args.id) } }
这会使用 id
输入参数值 1
替换 ${ctx.args.id}
并生成以下 JSON:
{ "version" : "2018-05-29", "operation" : "GetItem", "key" : { "id" : { "S" : "1" } } }
Amazon AppSync 使用此模板生成与 DynamoDB 通信和获取数据(或根据需要执行其他操作)的指令。数据返回后,Amazon AppSync 通过可选的可用于执行数据形状塑造或逻辑的响应映射模板以运行数据。例如,当我们从 DynamoDB 获得结果时,它们可能如下所示:
{ "id" : 1, "theTitle" : "Amazon AppSync works offline!", "theContent-part1" : "It also has realtime functionality", "theContent-part2" : "using GraphQL" }
您可以选择使用以下响应映射模板将两个字段联接成单一字段:
{ "id" : $util.toJson($context.data.id), "title" : $util.toJson($context.data.theTitle), "content" : $util.toJson("${context.data.theContent-part1} ${context.data.theContent-part2}") }
以下是将模板应用到数据后对数据进行塑造的方式:
{ "id" : 1, "title" : "Amazon AppSync works offline!", "content" : "It also has realtime functionality using GraphQL" }
此数据作为响应返回给客户端,如下所示:
{ "data": { "getPost": { "id" : 1, "title" : "Amazon AppSync works offline!", "content" : "It also has realtime functionality using GraphQL" } } }
请注意,在大多数情况下,响应映射模板是简单的数据传递,主要由于您返回的是单个项目还是项目列表而不同。对于单个项目,传递:
$util.toJson($context.result)
对于列表,通常传递的是:
$util.toJson($context.result.items)
要查看单元解析器和管道解析器的更多示例,请参阅解析器教程。
评估的映射模板反序列化规则
映射模板计算结果为字符串。在 Amazon AppSync 中,输出字符串必须遵循 JSON 结构才会有效。
此外,将强制执行以下反序列化规则。
JSON 对象中不允许使用重复的键
如果计算得出的映射模板字符串表示 JSON 对象或包含具有重复键的对象,则映射模板会返回以下错误消息:
Duplicate field 'aField' detected on Object. Duplicate JSON keys are not
allowed.
已计算的请求映射模板中的重复键示例:
{ "version": "2018-05-29", "operation": "Invoke", "payload": { "field": "getPost", "postId": "1", "field": "getPost" ## key 'field' has been redefined } }
要修复此错误,请不要重新定义 JSON 对象中的键。
JSON 对象中不允许使用尾随字符
如果计算得出的映射模板字符串表示 JSON 对象并包含尾随的无关字符,则映射模板会返回以下错误消息:
Trailing characters at the end of the JSON string are not allowed.
已计算的请求映射模板中的尾随字符示例:
{ "version": "2018-05-29", "operation": "Invoke", "payload": { "field": "getPost", "postId": "1", } }extraneouschars
要修复此错误,请确保评估后的模板严格评估为 JSON。