当 Lambda 介于两者之间时如何使用 AppSync 和 DynamoDB 正确格式化数据
How to properly format data with AppSync and DynamoDB when Lambda is in between
使用 AppSync 直接从 DynamoDB 接收数据似乎适用于我的情况,但是当我尝试在两者之间放置一个 lambda 函数时,我收到错误 "Can't resolve value (/issueNewMasterCard/masterCards) : type mismatch error, expected type LIST"
查看 AppSync cloudwatch 响应映射输出,我得到:
"context": {
"arguments": {
"userId": "18e946df-d3de-49a8-98b3-8b6d74dfd652"
},
"result": {
"Item": {
"masterCards": {
"L": [
{
"M": {
"cardId": {
"S": "95d67f80-b486-11e8-ba85-c3623f6847af"
},
"cardImage": {
"S": "https://s3.eu-central-1.amazonaws.com/logo.png"
},
"cardWallet": {
"S": "0xFDB17d12057b6Fe8c8c434653456435634565"
},...............
这是我配置响应映射模板的方式:
$utils.toJson($context.result.Item)
我正在做这个突变:
mutation IssueNewMasterCard {
issueNewMasterCard(userId:"18e946df-d3de-49a8-98b3-8b6d74dfd652"){
masterCards {
cardId
}
}
}
这是我的架构:
type User {
userId: ID!
masterCards: [MasterCard]
}
type MasterCard {
cardId: String
}
type Mutation {
issueNewMasterCard(userId: ID!): User
}
Lambda 函数:
exports.handler = (event, context, callback) => {
const userId = event.arguments.userId;
const userParam = {
Key: {
"userId":{S:userId}
},
TableName:"FidelityCardsUsers"
}
dynamoDB.getItem(userParam, function(err, data) {
if (err) {
console.log('error from DynamDB: ',err)
callback(err);
} else {
console.log('mastercards: ',JSON.stringify(data));
callback(null,data)
}
})
我认为问题在于您在使用 DynamoDB 数据源时使用的 getItem
与 aws-sdk 中的 DynamoDB.getItem
函数不同。
具体来说,数据源版本 returns 似乎是一个已经编组的响应(也就是说,不是 something: { L: [ list of things ] }
它只是 returns something: [ list of things]
)。
这很重要,因为这意味着您当前设置中的 $utils.toJson($context.result.Item)
正在返回 { masterCards: { L: [ ...
,这就是您看到类型错误的原因 - masterCards
在这种情况下是一个对象使用键 L
,而不是 array/list.
要在解析器中解决这个问题,您可以使用 $util.dynamodb.toDynamoDBJson(Object)
宏 (https://docs.aws.amazon.com/appsync/latest/devguide/resolver-util-reference.html#dynamodb-helpers-in-util-dynamodb)。即你的解析器应该是:
$util.dynamodb.toDynamoDBJson($context.result.Item)
或者您可能想查看 AWS.DynamoDB.DocumentClient
class (https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB/DocumentClient.html)。这包括 getItem
等版本,它们自动编组和解组专有的 DynamoDB 输入回本机 JSON。 (坦率地说,我发现它更好用并且一直在使用它)。
在那种情况下,您可以保留您的旧解析器,因为您将返回一个对象,其中masterCards
是只是一个 JSON 数组。
使用 AppSync 直接从 DynamoDB 接收数据似乎适用于我的情况,但是当我尝试在两者之间放置一个 lambda 函数时,我收到错误 "Can't resolve value (/issueNewMasterCard/masterCards) : type mismatch error, expected type LIST"
查看 AppSync cloudwatch 响应映射输出,我得到:
"context": {
"arguments": {
"userId": "18e946df-d3de-49a8-98b3-8b6d74dfd652"
},
"result": {
"Item": {
"masterCards": {
"L": [
{
"M": {
"cardId": {
"S": "95d67f80-b486-11e8-ba85-c3623f6847af"
},
"cardImage": {
"S": "https://s3.eu-central-1.amazonaws.com/logo.png"
},
"cardWallet": {
"S": "0xFDB17d12057b6Fe8c8c434653456435634565"
},...............
这是我配置响应映射模板的方式:
$utils.toJson($context.result.Item)
我正在做这个突变:
mutation IssueNewMasterCard {
issueNewMasterCard(userId:"18e946df-d3de-49a8-98b3-8b6d74dfd652"){
masterCards {
cardId
}
}
}
这是我的架构:
type User {
userId: ID!
masterCards: [MasterCard]
}
type MasterCard {
cardId: String
}
type Mutation {
issueNewMasterCard(userId: ID!): User
}
Lambda 函数:
exports.handler = (event, context, callback) => {
const userId = event.arguments.userId;
const userParam = {
Key: {
"userId":{S:userId}
},
TableName:"FidelityCardsUsers"
}
dynamoDB.getItem(userParam, function(err, data) {
if (err) {
console.log('error from DynamDB: ',err)
callback(err);
} else {
console.log('mastercards: ',JSON.stringify(data));
callback(null,data)
}
})
我认为问题在于您在使用 DynamoDB 数据源时使用的 getItem
与 aws-sdk 中的 DynamoDB.getItem
函数不同。
具体来说,数据源版本 returns 似乎是一个已经编组的响应(也就是说,不是 something: { L: [ list of things ] }
它只是 returns something: [ list of things]
)。
这很重要,因为这意味着您当前设置中的 $utils.toJson($context.result.Item)
正在返回 { masterCards: { L: [ ...
,这就是您看到类型错误的原因 - masterCards
在这种情况下是一个对象使用键 L
,而不是 array/list.
要在解析器中解决这个问题,您可以使用 $util.dynamodb.toDynamoDBJson(Object)
宏 (https://docs.aws.amazon.com/appsync/latest/devguide/resolver-util-reference.html#dynamodb-helpers-in-util-dynamodb)。即你的解析器应该是:
$util.dynamodb.toDynamoDBJson($context.result.Item)
或者您可能想查看 AWS.DynamoDB.DocumentClient
class (https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB/DocumentClient.html)。这包括 getItem
等版本,它们自动编组和解组专有的 DynamoDB 输入回本机 JSON。 (坦率地说,我发现它更好用并且一直在使用它)。
在那种情况下,您可以保留您的旧解析器,因为您将返回一个对象,其中masterCards
是只是一个 JSON 数组。