如何指定要通过AppSync从DynamoDB返回的属性



我有一个AppSync管道解析程序。第一个函数在ElasticSearch数据库中查询DynamoDB键。第二个函数使用提供的键查询DynamoDB。这一切都很好,直到我遇到了AppSync的1MB限制。由于大多数数据都在我不需要的几个属性/列中,所以我想将结果限制在我需要的属性中。

我尝试添加AttributesToGet和ProjectionExpression(从这里开始(,但都出现了错误,比如:

{
"data": {
"getItems": null
},
"errors": [
{
"path": [
"getItems"
],
"data": null,
"errorType": "MappingTemplate",
"errorInfo": null,
"locations": [
{
"line": 2,
"column": 3,
"sourceName": null
}
],
"message": "Unsupported element '$[tables][dev-table-name][projectionExpression]'."
}
]
}

我的DynamoDB函数请求映射模板看起来像(只要数据小于1MB,就会返回结果(:

#set($ids = [])
#foreach($pResult in ${ctx.prev.result})
#set($map = {})
$util.qr($map.put("id", $util.dynamodb.toString($pResult.id)))
$util.qr($map.put("ouId", $util.dynamodb.toString($pResult.ouId)))
$util.qr($ids.add($map))
#end
{
"version" : "2018-05-29",
"operation" : "BatchGetItem",
"tables" : {
"dev-table-name": {
"keys": $util.toJson($ids),
"consistentRead": false
}
}
}

2023更新:

正如Harish Vemula所指出的那样,预测现在已经实施。

我的问题的解决方案是:

#set($ids = [])
#foreach($pResult in ${ctx.prev.result})
#set($map = {})
$util.qr($map.put("id", $util.dynamodb.toString($pResult.id)))
$util.qr($map.put("ouId", $util.dynamodb.toString($pResult.ouId)))
$util.qr($ids.add($map))
#end
{
"version" : "2018-05-29",
"operation" : "BatchGetItem",
"tables" : {
"dev-table-name": {
"keys": $util.toJson($ids),
"consistentRead": false,
"projection": {
"expression" : "#id, #ouId, #otherField1, #otherField2",
"expressionNames": {
"#id": "id",
"#ouId": "ouId",
"#otherField1": "otherField1",
"#otherField2": "otherField2"
}
}
}
}

我想我必须转义数组中的映射,但在表达式和expressionNames中指定数组的名称是返回整个数组所需的全部内容。

有用的链接:

DynamoDB的解析器映射模板参考-BatchGetItem
  • DynamoDB的解析器映射模板参考-Projections
  • 解析程序映射模板上下文引用-信息
    • selectionSetList可用于确定已请求的字段
  • 教程:DynamoDB批处理解析器
  • DynamoDB中的表达式属性名称-嵌套属性
    • 注意:这是针对AWS CLI的,但转义规则似乎是相同的

  • 原始答案:

    我联系了AWS的人员,他们确认目前不支持ProjectionExpression,他们还需要一段时间才能使用它。

    相反,我创建了一个lambda来从DynamoDB中提取数据。

    为了限制来自DynamoDB的结果,我在AppSync中使用$ctx.info.selectionSetList来获得请求列的列表,然后使用该列表来指定要从DynamoDB中提取的数据。我需要获得多个结果,保持顺序,所以我使用了BatchGetItem,然后使用LINQ将结果与原始ID列表合并(这将DynamoDB结果按正确的顺序放回,因为C#中的BatchGetItem不像AppSync版本那样保留排序顺序(。

    因为我在许多库中使用C#,所以冷启动时间有点长,所以我在Linux上使用了JITed之前的Lambda Layers,这使我们可以将冷启动时间从大约1.8秒降低到大约1秒(当Lambda使用1024 GB RAM时(。

    AppSync现在支持DynamoDB投影表达式,使用它可以指定解析器中所需的属性。

    在您的用例中,请按照下面的BatchGetItem文档使用投影表达式传递参数。

    https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference-dynamodb.html#aws-appsync解析器映射模板参考发电机数据库批量获取项目

    您的代码如下所示,在这里,我们只指定要从批处理获取操作中检索的作者和id字段

    #set($ids = [])
    #foreach($pResult in ${ctx.prev.result})
    #set($map = {})
    $util.qr($map.put("id", $util.dynamodb.toString($pResult.id)))
    $util.qr($map.put("ouId", $util.dynamodb.toString($pResult.ouId)))
    $util.qr($ids.add($map))
    #end
    {
    "version" : "2018-05-29",
    "operation" : "BatchGetItem",
    "tables" : {
    "dev-table-name": {
    "keys": $util.toJson($ids),
    "consistentRead": false,
    "projection" : {
    "expression" : "#author, id",
    "expressionNames" : {
    "#author" : "author"
    }
    }
    }
    }
    }
    

    更新的答案-2023

    感谢@HarishVemula指出这次AWS更新-现在可以在请求模板中定义投影,例如:

    {
    "version" : "2017-02-28",
    "operation" : "GetItem",
    "key" : {
    "id" : $util.dynamodb.toDynamoDBJson($ctx.args.id)
    },
    "projection" : {
    "expression" : "#author, id, title",
    "expressionNames" : { "#author" : "author"}
    }
    }
    

    旧答案

    AppSync不支持投影,但您可以明确定义在响应模板中返回哪些字段,而不是返回整个结果集。

    {
    "id": "$ctx.result.get('id')",
    "name": "$ctx.result.get('name')",
    ...
    }
    

    最新更新