我有一个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- selectionSetList可用于确定已请求的字段
- 注意:这是针对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')",
...
}