如何直接从请求映射器 return?
How to return directly from the request mapper?
考虑以下 GraphQL 模板:
type Foo {
id: ID!
bars: Bars
}
type Bar {
id: ID!
name: String!
}
type Bars {
items: [Bar]!
nextToken: String
}
Foo 类型中 bars
字段的映射模板如下所示:
#set($ids = [])
#foreach($id in $context.source.bars)
#set($map = {})
$util.qr($map.put("id", $util.dynamodb.toString($id)))
$util.qr($ids.add($map))
#end
{
"version" : "2018-05-29",
"operation" : "BatchGetItem",
"tables" : {
"barsTable" : {
"keys": $util.toJson($ids),
"consistentRead": true
}
}
}
这很好用。但是如果 bars
字段包含空数组 []
,模板显然会崩溃并出现以下错误:
"errors": [
{
"path": [
"getFoo",
"bars"
],
"data": null,
"errorType": "MappingTemplate",
"errorInfo": null,
"locations": [
{
"line": 59,
"column": 7,
"sourceName": null
}
],
"message": "RequestItem keys '$[tables][barsTable]' can't be empty"
}
]
所以我的问题是:
如何在 $context.source.bars
为空时阻止执行查询并仅 return 向响应模板发送一个空数组?
您可以使用
#if(!$array.isEmpty())
//do something
#else
//do something else
#end
更多信息您可以参考解析器映射模板参考指南here
我试图重现你的用例,最后我想出了一个解决问题的技巧。
示例模式:
type Query {
getTests(ids: [ID!]): [Test]
}
type Test {
id: ID!
title: String!
}
schema {
query: Query
}
解决方案
## REQUEST MAPPING
#set($ids = [])
## CREATE A FAKE-ID TO RETURN NULL ONLY IF ids IS NULL OR EMPTY
#if( $ctx.args.ids.isEmpty() || $util.isNull($ctx.args.ids) )
#set($map = {})
$util.qr($map.put("id", $util.dynamodb.toString("fake-id-to-return-null")))
$util.qr($ids.add($map))
#else
#foreach($id in $ctx.args.ids)
#set($map = {})
$util.qr($map.put("id", $util.dynamodb.toString($id)))
$util.qr($ids.add($map))
#end
#end
{
"version" : "2018-05-29",
"operation" : "BatchGetItem",
"tables" : {
"TestTable": {
"keys": $util.toJson($ids),
"consistentRead": true
}
}
}
## RESPONSE MAPPING
$utils.toJson($ctx.result.data.TestTable)
另一个类似的解决方案
#if( !($util.isNull($ctx.args.ids) || $ctx.args.ids.isEmpty()) )
#set($ids = [])
#foreach($id in $ctx.args.ids)
#set($map = {})
$util.qr($map.put("id", $util.dynamodb.toString($id)))
$util.qr($ids.add($map))
#end
{
"version" : "2018-05-29",
"operation" : "BatchGetItem",
"tables" : {
"TestTable": {
"keys": $util.toJson($ids),
"consistentRead": true
}
}
}
#else
{
"version": "2017-02-28",
"operation": "GetItem",
"key": {
"id": $util.dynamodb.toDynamoDBJson("."),
}
}
#end
测试
我花了好几个小时才弄明白这个。就像从请求映射器调用 #return(data)
一样简单。
你的情况:
#if ($context.source.bars.size() <= 0)
#return([])
#end
#set($ids = [])
#foreach($id in $context.source.bars)
#set($map = {})
$util.qr($map.put("id", $util.dynamodb.toString($id)))
$util.qr($ids.add($map))
#end
{
"version" : "2018-05-29",
"operation" : "BatchGetItem",
"tables" : {
"barsTable" : {
"keys": $util.toJson($ids),
"consistentRead": true
}
}
}
考虑以下 GraphQL 模板:
type Foo {
id: ID!
bars: Bars
}
type Bar {
id: ID!
name: String!
}
type Bars {
items: [Bar]!
nextToken: String
}
Foo 类型中 bars
字段的映射模板如下所示:
#set($ids = [])
#foreach($id in $context.source.bars)
#set($map = {})
$util.qr($map.put("id", $util.dynamodb.toString($id)))
$util.qr($ids.add($map))
#end
{
"version" : "2018-05-29",
"operation" : "BatchGetItem",
"tables" : {
"barsTable" : {
"keys": $util.toJson($ids),
"consistentRead": true
}
}
}
这很好用。但是如果 bars
字段包含空数组 []
,模板显然会崩溃并出现以下错误:
"errors": [
{
"path": [
"getFoo",
"bars"
],
"data": null,
"errorType": "MappingTemplate",
"errorInfo": null,
"locations": [
{
"line": 59,
"column": 7,
"sourceName": null
}
],
"message": "RequestItem keys '$[tables][barsTable]' can't be empty"
}
]
所以我的问题是:
如何在 $context.source.bars
为空时阻止执行查询并仅 return 向响应模板发送一个空数组?
您可以使用
#if(!$array.isEmpty())
//do something
#else
//do something else
#end
更多信息您可以参考解析器映射模板参考指南here
我试图重现你的用例,最后我想出了一个解决问题的技巧。
示例模式:
type Query {
getTests(ids: [ID!]): [Test]
}
type Test {
id: ID!
title: String!
}
schema {
query: Query
}
解决方案
## REQUEST MAPPING
#set($ids = [])
## CREATE A FAKE-ID TO RETURN NULL ONLY IF ids IS NULL OR EMPTY
#if( $ctx.args.ids.isEmpty() || $util.isNull($ctx.args.ids) )
#set($map = {})
$util.qr($map.put("id", $util.dynamodb.toString("fake-id-to-return-null")))
$util.qr($ids.add($map))
#else
#foreach($id in $ctx.args.ids)
#set($map = {})
$util.qr($map.put("id", $util.dynamodb.toString($id)))
$util.qr($ids.add($map))
#end
#end
{
"version" : "2018-05-29",
"operation" : "BatchGetItem",
"tables" : {
"TestTable": {
"keys": $util.toJson($ids),
"consistentRead": true
}
}
}
## RESPONSE MAPPING
$utils.toJson($ctx.result.data.TestTable)
另一个类似的解决方案
#if( !($util.isNull($ctx.args.ids) || $ctx.args.ids.isEmpty()) )
#set($ids = [])
#foreach($id in $ctx.args.ids)
#set($map = {})
$util.qr($map.put("id", $util.dynamodb.toString($id)))
$util.qr($ids.add($map))
#end
{
"version" : "2018-05-29",
"operation" : "BatchGetItem",
"tables" : {
"TestTable": {
"keys": $util.toJson($ids),
"consistentRead": true
}
}
}
#else
{
"version": "2017-02-28",
"operation": "GetItem",
"key": {
"id": $util.dynamodb.toDynamoDBJson("."),
}
}
#end
测试
我花了好几个小时才弄明白这个。就像从请求映射器调用 #return(data)
一样简单。
你的情况:
#if ($context.source.bars.size() <= 0)
#return([])
#end
#set($ids = [])
#foreach($id in $context.source.bars)
#set($map = {})
$util.qr($map.put("id", $util.dynamodb.toString($id)))
$util.qr($ids.add($map))
#end
{
"version" : "2018-05-29",
"operation" : "BatchGetItem",
"tables" : {
"barsTable" : {
"keys": $util.toJson($ids),
"consistentRead": true
}
}
}