当 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 数组。