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

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

Lambda 的解析器映射模板参考

注意

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

您可以使用 Amazon AppSync 函数和解析器来调用位于您账户中的 Lambda 函数。在将请求负载和 Lambda 函数返回给客户之前,您可以调整请求负载和 Lambda 函数的响应。您还可以使用映射模板来提示 Amazon AppSync 要调用的操作的性质。本节介绍了支持的 Lambda 操作的各种映射模板。

请求映射模板

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 }

以下示例使用了一个invoke操作,其有效载荷数据是 GraphQL 架构中的getPost字段,其参数来自上下文:

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

版本

所有请求映射模板都通用,version定义了模板使用的版本。version是必填的,是一个静态值:

"version": "2018-05-29"

操作

Lambda 数据源允许您在operation字段中定义两个操作:Invoke和。BatchInvokeInvoke操作允许 Amazon AppSync 你为每个 GraphQL 字段解析器调用你的 Lambda 函数。 BatchInvoke指示 Amazon AppSync 对当前 GraphQL 字段进行批量请求。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,映射模板将应用于批次中的每个字段解析器。为简洁起见,将所有已解析的映射模板payload值 Amazon AppSync 合并到与映射模板匹配的单个对象下的列表中。以下示例模板显示合并:

{ "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列表中的每个元素对应一个批次项目。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 ]

有效负载

payload字段是一个容器,用于将任何格式正确的 JSON 传递给 Lambda 函数。如果该operation字段设置为BatchInvoke,则 Amazon AppSync 将现有payload值换成一个列表。payload 字段为可选项。

调用类型

Lambda 数据源允许您定义两种调用类型:和。RequestResponse Event调用类型与 Lambda API 中定义的调用类型同义。RequestResponse调用类型允许 Amazon AppSync 同步调用您的 Lambda 函数以等待响应。该Event调用允许您异步调用 Lambda 函数。有关 Lambda 如何处理Event调用类型请求的更多信息,请参阅异步调用。invocationType 字段为可选项。如果请求中未包含此字段, Amazon 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调用类型字段结合使用时,将以与上述相同的方式 Amazon AppSync 合并字段解析器,然后将请求作为异步事件传递给您的 Lambda 函数,其为值列表payload。我们建议您禁用Event调用类型解析器的解析器缓存,因为如果出现缓存命中,这些解析器不会发送到 Lambda。

响应映射模板

与其他数据源一样,您的 Lambda 函数发送的响应必须转换为 GraphQL 类型。 Amazon AppSync

Lambda 函数的结果是在通过 Velocity 模板语言 (VTL) $context.result 属性提供的 context 对象上设置的。

如果 Lambda 函数响应的形状与 GraphQL 类型的形状完全匹配,您可以使用以下响应映射模板转发响应:

$util.toJson($context.result)

没有必填字段,也没有形状限制应用于响应映射模板。但是,由于 GraphQL 是强类型化的,因此解析的映射模板必须与预期的 GraphQL 类型匹配。

Lambda 函数批处理的响应

如果该operation字段设置为BatchInvoke, Amazon AppSync则需要从 Lambda 函数返回的项目列表。 Amazon AppSync 为了将每个结果映射回原始请求项,响应列表的大小和顺序必须匹配。在响应列表中包含null项目是有效$ctx.result的;相应地设置为 null

直接 Lambda 解析器

如果您想完全避免使用映射模板, Amazon AppSync 可以为您的 Lambda 函数提供默认负载,并为 GraphQL 类型提供默认 Lambda 函数响应。您可以选择提供请求模板、响应模板或两者都不提供,然后进行相应的 Amazon AppSync 处理。

直接 Lambda 请求映射模板

如果未提供请求映射模板,则 Amazon AppSync 会将该Context对象作为操作直接发送到您的 Lambda 函数。Invoke有关 Context 对象结构的更多信息,请参阅 解析器映射模板上下文参考

直接 Lambda 响应映射模板

如果未提供响应映射模板,则在收到 Lambda 函数的响应后 Amazon AppSync 执行以下两项操作之一。如果您没有提供请求映射模板,或者您在版本中提供了请求映射模板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 解析器响应中的自定义错误处理

您可以通过引发自定义异常,自定义直接 Lambda 解析器调用的 Lambda 函数的错误响应。以下示例演示如何使用创建自定义异常 JavaScript:

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

在引发异常时,errorTypeerrorMessage 分别是引发的自定义错误的 namemessage

如果errorTypeUnauthorizedException,则 Amazon AppSync返回默认消息 ("You are not authorized to make this call.") 而不是自定义消息。

以下片段是演示自定义的 GraphQL 响应示例:errorType

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

直接 Lambda 解析器:已启用批处理

您可以通过在解析器上配置 maxBatchSize,为直接 Lambda 解析器启用批处理。如果设置0为大于 D maxBatchSize irect Lambda 解析器的值,则会分批向您的 Lambda 函数 Amazon AppSync 发送大小不超过的请求。maxBatchSize

在 Direct Lambda 解析器0上设置maxBatchSize为会关闭批处理。

有关 Lambda 解析器上的批处理的工作方式的更多信息,请参阅高级使用案例:批处理

请求映射模板

启用批处理但未提供请求映射模板时, Amazon AppSync 会将Context对象列表作为BatchInvoke操作直接发送到您的 Lambda 函数。

响应映射模板

如果启用了批处理并且未提供响应映射模板,响应逻辑相当于以下响应映射模板:

#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 对象列表相同。您可以为特定结果提供 errorMessageerrorType 以返回各个错误。列表中的每个结果采用以下格式:

{ "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 的错误

您可以通过在 Lambda 函数中引发异常或错误,为所有结果返回错误。如果批处理请求的负载请求或响应太大,Lambda 将返回错误。在这种情况下,您应该考虑减少 maxBatchSize 或减少响应负载大小。

有关处理各个错误的信息,请参阅返回单个错误

示例 Lambda 函数

使用以下架构,您可以为Post.relatedPosts字段解析器创建 Direct Lambda 解析器,并通过上述设置启用批处理:maxBatchSize0

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

在以下查询中,将为批量请求调用 Lambda 函数以解析 relatedPosts

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' } } }) }