AWS Appsync 批处理解析器
AWS Appsync Batch Resolver
现在为此苦苦挣扎了一段时间,我将问题的查询名称更改为 getDeviceReadings,我一直在使用 getAllUserDevices(抱歉造成任何混淆)
type Device {
id: String
device: String!
}
type Reading {
device: String
time: Int
}
type PaginatedDevices {
devices: [Device]
readings: [Reading]
nextToken: String
}
type Query {
getDevicesReadings(nextToken: String, count: Int): PaginatedDevices
}
然后我有一个查询 getDevicesReadings 的解析器,它工作正常并且 returns 用户到目前为止拥有的所有设备都很好
{
"version": "2017-02-28",
"operation": "Query",
"query" : {
"expression": "id = :id",
"expressionValues" : {
":id" : { "S" : "${context.identity.username}" }
}
}
#if( ${context.arguments.count} )
,"limit": ${context.arguments.count}
#end
#if( ${context.arguments.nextToken} )
,"nextToken": "${context.arguments.nextToken}"
#end
}
现在我想 return 设备基于源结果的所有读数,所以我在 getDevicesReadings/readings
上有一个解析器
#set($ids = [])
#foreach($id in ${ctx.source.devices})
#set($map = {})
$util.qr($map.put("device", $util.dynamodb.toString($id.device)))
$util.qr($ids.add($map))
#end
{
"version" : "2018-05-29",
"operation" : "BatchGetItem",
"tables" : {
"readings": {
"keys": $util.toJson($ids),
"consistentRead": true
}
}
}
像这样的响应映射..
$utils.toJson($context.result.data.readings)
我运行一个查询
query getShit{
getDevicesReadings{
devices{
device
}
readings{
device
time
}
}
}
这个return是下面的结果
{
"data": {
"getAllUserDevices": {
"devices": [
{
"device": "123"
},
{
"device": "a935eeb8-a0d0-11e8-a020-7c67a28eda41"
}
],
"readings": [
null,
null
]
}
}
}
正如您在图像上看到的,主分区键是读数上的设备 table 我查看了日志,我有以下内容
抱歉,如果您无法阅读日志,它基本上说有未处理的密钥
和下面的错误信息
"message": "The provided key element does not match the schema (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException; Request ID: 0H21LJE234CH1GO7A705VNQTJVVV4KQNSO5AEMVJF66Q9ASUAAJG)",
我在猜测我的映射不太正确,我将读数作为我的密钥传递?
非常感谢任何帮助
所以当你有主排序键时你不能有批处理解析器?!
所以答案是创建一个 lambda 函数并将其添加为我的解析器
import boto3
from boto3.dynamodb.conditions import Key
def lambda_handler(event, context):
list = []
for device in event['source']['devices'] :
dynamodb = boto3.resource('dynamodb')
readings = dynamodb.Table('readings')
response = readings.query(
KeyConditionExpression=Key('device').eq(device['device'])
)
items = response['Items']
list.extend(items)
return list
您是对的,您提供的请求映射模板与 readings
table 上的主键不匹配。 BatchGetItem
期望 keys
成为主键,但是您只传递散列键。
要使 BatchGetItem
调用成功,您必须传递 哈希和排序键,因此在这种情况下,device
和 time
]属性。
也许 readings
table 上的 Query
更合适?
不,当您有主排序键时,您绝对可以使用批处理解析器。您的示例中的错误是您没有向解析器提供主排序键。
此代码需要提供 "time" 和 "device",因为您需要两者才能完全指定主键。
#set($ids = [])
#foreach($id in ${ctx.source.devices})
#set($map = {})
$util.qr($map.put("device", $util.dynamodb.toString($id.device)))
$util.qr($ids.add($map))
#end
你应该有类似的东西:
#set($ids = [])
#foreach($id in ${ctx.source.devices})
#set($map = {})
# The tables primary key is made up of "device" AND "time"
$util.qr($map.put("device", $util.dynamodb.toString($id.device)))
$util.qr($map.put("time", $util.dynamodb.toString($id.time)))
$util.qr($ids.add($map))
#end
如果您想获取许多共享相同 "device" 值但具有不同 "time" 值的记录,您需要使用 DynamoDB 查询操作,而不是批量获取。
现在为此苦苦挣扎了一段时间,我将问题的查询名称更改为 getDeviceReadings,我一直在使用 getAllUserDevices(抱歉造成任何混淆)
type Device {
id: String
device: String!
}
type Reading {
device: String
time: Int
}
type PaginatedDevices {
devices: [Device]
readings: [Reading]
nextToken: String
}
type Query {
getDevicesReadings(nextToken: String, count: Int): PaginatedDevices
}
然后我有一个查询 getDevicesReadings 的解析器,它工作正常并且 returns 用户到目前为止拥有的所有设备都很好
{
"version": "2017-02-28",
"operation": "Query",
"query" : {
"expression": "id = :id",
"expressionValues" : {
":id" : { "S" : "${context.identity.username}" }
}
}
#if( ${context.arguments.count} )
,"limit": ${context.arguments.count}
#end
#if( ${context.arguments.nextToken} )
,"nextToken": "${context.arguments.nextToken}"
#end
}
现在我想 return 设备基于源结果的所有读数,所以我在 getDevicesReadings/readings
上有一个解析器#set($ids = [])
#foreach($id in ${ctx.source.devices})
#set($map = {})
$util.qr($map.put("device", $util.dynamodb.toString($id.device)))
$util.qr($ids.add($map))
#end
{
"version" : "2018-05-29",
"operation" : "BatchGetItem",
"tables" : {
"readings": {
"keys": $util.toJson($ids),
"consistentRead": true
}
}
}
像这样的响应映射..
$utils.toJson($context.result.data.readings)
我运行一个查询
query getShit{
getDevicesReadings{
devices{
device
}
readings{
device
time
}
}
}
这个return是下面的结果
{
"data": {
"getAllUserDevices": {
"devices": [
{
"device": "123"
},
{
"device": "a935eeb8-a0d0-11e8-a020-7c67a28eda41"
}
],
"readings": [
null,
null
]
}
}
}
正如您在图像上看到的,主分区键是读数上的设备 table 我查看了日志,我有以下内容
抱歉,如果您无法阅读日志,它基本上说有未处理的密钥
和下面的错误信息
"message": "The provided key element does not match the schema (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException; Request ID: 0H21LJE234CH1GO7A705VNQTJVVV4KQNSO5AEMVJF66Q9ASUAAJG)",
我在猜测我的映射不太正确,我将读数作为我的密钥传递?
非常感谢任何帮助
所以当你有主排序键时你不能有批处理解析器?!
所以答案是创建一个 lambda 函数并将其添加为我的解析器
import boto3
from boto3.dynamodb.conditions import Key
def lambda_handler(event, context):
list = []
for device in event['source']['devices'] :
dynamodb = boto3.resource('dynamodb')
readings = dynamodb.Table('readings')
response = readings.query(
KeyConditionExpression=Key('device').eq(device['device'])
)
items = response['Items']
list.extend(items)
return list
您是对的,您提供的请求映射模板与 readings
table 上的主键不匹配。 BatchGetItem
期望 keys
成为主键,但是您只传递散列键。
要使 BatchGetItem
调用成功,您必须传递 哈希和排序键,因此在这种情况下,device
和 time
]属性。
也许 readings
table 上的 Query
更合适?
不,当您有主排序键时,您绝对可以使用批处理解析器。您的示例中的错误是您没有向解析器提供主排序键。
此代码需要提供 "time" 和 "device",因为您需要两者才能完全指定主键。
#set($ids = [])
#foreach($id in ${ctx.source.devices})
#set($map = {})
$util.qr($map.put("device", $util.dynamodb.toString($id.device)))
$util.qr($ids.add($map))
#end
你应该有类似的东西:
#set($ids = [])
#foreach($id in ${ctx.source.devices})
#set($map = {})
# The tables primary key is made up of "device" AND "time"
$util.qr($map.put("device", $util.dynamodb.toString($id.device)))
$util.qr($map.put("time", $util.dynamodb.toString($id.time)))
$util.qr($ids.add($map))
#end
如果您想获取许多共享相同 "device" 值但具有不同 "time" 值的记录,您需要使用 DynamoDB 查询操作,而不是批量获取。