解析器映射模板概述 - Amazon AppSync
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

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

解析器映射模板概述

注意

我们现在主要支持 APPSYNC_JS 运行时环境及其文档。请考虑使用 APPSYNC_JS 运行时环境和此处的指南。

在 Amazon AppSync 中,您可以对资源执行操作以响应 GraphQL 请求。对于您希望运行查询或变更的每个 GraphQL 字段,必须附加解析器才能与数据源通信。通常,通信是通过数据源特有的参数或操作完成的。

解析器是 GraphQL 和数据源之间的连接器。它们指示 Amazon AppSync 如何将传入的 GraphQL 请求转换为后端数据源的指令,以及如何将该数据源的响应转换回 GraphQL 响应。它们是使用 Apache Velocity 模板语言 (VTL) 编写的,该语言将您的请求作为输入,并输出包含解析器指令的 JSON 文档。您可以使用映射模板执行简单的指令(例如,从 GraphQL 字段中传入参数),也可以执行更复杂的指令(例如,循环访问各个参数以构建项目,然后将该项目插入到 DynamoDB 中)。

在 Amazon AppSync 中具有两种类型的解析器,它们以略微不同的方式使用映射模板:

  • 单位解析器

  • 管道解析器

单位解析器

单位解析器是独立的实体,仅包含请求和响应模板。将它们用于简单、单一的操作(例如,列出来自单个数据源的项目)。

  • 请求模板:在解析 GraphQL 操作后获取传入请求,并将其转换为选定数据源操作的请求配置。

  • 响应模板:解释来自数据源的响应,并将其映射到 GraphQL 字段输出类型的形状。

管道解析器

管道解析器包含一个或多个按顺序执行的函数。每个函数包含一个请求模板和一个响应模板。管道解析器还具有一个之前 模板和一个之后 模板,它们位于模板包含的一系列函数两侧。之后 模板映射到 GraphQL 字段输出类型。管道解析器与单位解析器的不同之处在于响应模板映射输出的方式。管道解析器可以映射到所需的任何输出,包括另一个函数的输入或管道解析器的之后 模板。

管道解析器函数 允许您编写可在架构中的多个解析器之间重复使用的通用逻辑。函数直接附加到数据源,并且像单位解析器一样,包含相同的请求和响应映射模板格式。

下图说明了左侧单位解析器和右侧管道解析器的流程。


            与单个数据源通信的单位解析器的图表以及与多个数据源通信的管道解析器的图表。

管道解析器包含单位解析器支持的功能的超集以及更多功能,但代价是稍微复杂一些。

管道解析器剖析

管道解析器由之前映射模板、之后映射模板和一组函数组成。每个函数具有对数据源执行的请求映射模板和响应映射模板。由于管道解析器将执行委托给函数列表,因此它不会链接到任何数据源。单位解析器和函数是对数据源执行操作的基元。有关更多信息,请参阅解析器映射模板概述

之前映射模板

管道解析器的请求映射模板或预备步骤允许您在执行定义的函数之前执行一些准备逻辑。

函数列表

管道解析器将按顺序运行的函数的列表。管道解析器请求映射模板评估的结果可供第一个函数用作 $ctx.prev.result。每个函数输出可供下一个函数用作 $ctx.prev.result

之后映射模板

管道解析器的响应映射模板或后续步骤允许您执行从最后一个函数的输出到预期 GraphQL 字段类型的一些最终映射逻辑。函数列表中最后一个函数的输出可在管道解析器映射模板中用作 $ctx.prev.result$ctx.result

执行流程

假定一个管道解析器由两个函数组成,下面的列表表示调用解析器时的执行流程:

  1. 管道解析器的之前映射模板

  2. 函数 1:函数请求映射模板

  3. 函数 1:数据源调用

  4. 函数 1:函数响应映射模板

  5. 函数 2:函数请求映射模板

  6. 函数 2:数据源调用

  7. 函数 2:函数响应映射模板

  8. 管道解析器的之后映射模板

注意

管道解析器执行流是单向的,并在解析器上静态定义。

非常有用的 Apache Velocity 模板语言 (VTL) 实用程序

随着应用程序复杂性的增加,VTL 实用工具和指令在这里有助于提高开发效率。在使用管道解析器时,以下实用工具可为您提供帮助。

$ctx.stash

存储区是一个在每个解析器和函数映射模板中提供的Map。同一存储区实例通过单个解析器生效。这意味着,您可以使用存储区来跨请求和响应映射模板以及管道解析器中的函数传递任意数据。存储区公开与 Java 映射数据结构相同的方法。

$ctx.prev.result

$ctx.prev.result 表示在管道解析器中执行的上一个操作的结果。

如果上一个操作是管道解析器的之前映射模板,则 $ctx.prev.result 表示模板评估的输出,并提供给管道中的第一个函数。如果上一个操作是第一个函数,则 $ctx.prev.result 表示第一个函数的输出,并且可供管道中的第二个函数使用。如果上一个操作是最后一个函数,则 $ctx.prev.result 表示最后一个函数的输出,并提供给管道解析器的之后映射模板。

#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 签名,请访问解析器映射模板实用程序参考

$util.appendError

$util.appendError 类似于 $util.error(),主要区别在于前者不会中断映射模板的评估。相反,它指示该字段存在错误,但允许评估模板并因此会返回数据。在函数中使用 $util.appendError 将不会中断管道的执行流。有关更多详细信息和其他 $util.error 签名,请访问解析器映射模板实用程序参考

示例 模板

假设您在名为 getPost(id:ID!) 的字段上具有 DynamoDB 数据源和单位解析器,该解析器使用以下 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。