如何直接从请求映射器 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
         }
     }
}