【问题标题】:How to create AppSync DynamoDB resolver for object with relationships如何为具有关系的对象创建 AppSync DynamoDB 解析器
【发布时间】:2020-04-28 14:21:23
【问题描述】:

我有一个包含 GamesPlayers 的 DynamoDB 表。我目前有以下适用于我的 AppSync getGame 查询的 Lambda 解析器。问题是,是否可以使用具有相同功能的速度模板编写 DynamoDB 解析器,这样我就可以避免 lambda 调用。

const AWS = require('aws-sdk');
const docClient = new AWS.DynamoDB.DocumentClient();

exports.handler = async (event) => {
    let result = null;
    let params;
    switch(event.field) {
        case "getGame":
            const id = event.arguments.id;
            if (!id) {
                throw new Error('Missing game id');
            };
            params = {
                TableName: 'games',
                KeyConditionExpression: 'pk = :pk AND sk = :sk',
                ExpressionAttributeValues: {
                  ':pk': 'game',
                  ':sk': `meta_${id}`
                }
            };
            const game = (await docClient.query(params).promise()).Items[0];

            // get players
            const gameKey = `game_${game.sk.split('_')[1]}_${game.sk.split('_')[2]}`;            
            params = {
                TableName: 'games',
                KeyConditionExpression: 'pk = :pk AND begins_with(sk, :sk)',
                ExpressionAttributeValues: {
                    ':pk': gameKey,
                    ':sk': 'player_'
                }
            };
            game.players = (await docClient.query(params).promise()).Items;
            result = game;
            break;            
    }
    return result;
};

结果看起来像

{
  "gsipk": "NEW_OPEN",
  "sk": "meta_1578241126110_35660fcc-3cde-4d30-9ebd-09abba1aedf7",
  "gsisk": "level_1_players_4",
  "pk": "game",
  "players": [
    {
      "gsipk": "player_3a7bb19c-0ccd-42df-a606-acd8b1f5e288",
      "gsisk": "game_1578241126110_35660fcc-3cde-4d30-9ebd-09abba1aedf7",
      "points": 0,
      "num": 4,
      "place": null,
      "sk": "player_3a7bb19c-0ccd-42df-a606-acd8b1f5e288",
      "pieces": [],
      "wilds": 0,
      "pk": "game_1578241126110_35660fcc-3cde-4d30-9ebd-09abba1aedf7",
      "color": "gold",
      "pows": 0
    },
    {
      "gsipk": "player_96b772b1-4127-43da-b550-029d5c632675",
      "gsisk": "game_1578241126110_35660fcc-3cde-4d30-9ebd-09abba1aedf7",
      "points": 0,
      "num": 2,
      "place": null,
      "sk": "player_96b772b1-4127-43da-b550-029d5c632675",
      "pieces": [],
      "wilds": 0,
      "pk": "game_1578241126110_35660fcc-3cde-4d30-9ebd-09abba1aedf7",
      "color": "blue",
      "pows": 0
    },
    {
      "gsipk": "player_9d30c675-930f-401b-ac5f-8db32bb2acb8",
      "gsisk": "game_1578241126110_35660fcc-3cde-4d30-9ebd-09abba1aedf7",
      "points": 0,
      "num": 3,
      "place": null,
      "sk": "player_9d30c675-930f-401b-ac5f-8db32bb2acb8",
      "pieces": [],
      "wilds": 0,
      "pk": "game_1578241126110_35660fcc-3cde-4d30-9ebd-09abba1aedf7",
      "color": "green",
      "pows": 0
    },
    {
      "gsipk": "player_ab179ad1-a160-44f8-b438-0e93385b6c47",
      "gsisk": "game_1578241126110_35660fcc-3cde-4d30-9ebd-09abba1aedf7",
      "points": 0,
      "num": 1,
      "place": null,
      "sk": "player_ab179ad1-a160-44f8-b438-0e93385b6c47",
      "pieces": [],
      "wilds": 0,
      "pk": "game_1578241126110_35660fcc-3cde-4d30-9ebd-09abba1aedf7",
      "color": "red",
      "pows": 0
    }
  ]
}

【问题讨论】:

  • 能否附上表格结构或示例数据?
  • 样本数据可见上面results。但是,我确实重构了表格,并且能够达到预期的结果,请参见下面的答案!

标签: amazon-dynamodb aws-appsync


【解决方案1】:

除非您重新映射数据以便能够在一个请求中获取所有项目,否则您将需要 Pipeline resolvers.。总之,管道是在前/后模板中包装的多个解析器。

在您的情况下,这些之前/之后的模板并未真正使用,因此基本设置是:

在模板之前(什么都不需要,所以空 json 就可以了)

{}

模板之后(传递之前调用的结果)

$util.toJson($ctx.result)

然后您将拥有 2 个 DynamoDB 解析器。这些与您之前可能已经完成的其他 DynamoDB 解析器相同,除了在第二个解析器中,为了访问第一个 DynamoDB 解析器结果,您将使用$ctx.prev.result。因此,假设您在第一次调用的响应中传递了游戏 ID:

{
   "game_id": "$ctx.result.get('theGameId')",
    ...
}

然后可以在第二个请求模板中以$ctx.prev.result.game_id 访问它。您也可以改用 stash - $ctx.stash.put()$ctx.prev.get()。如果您需要在 BEFORE 请求(我们现在为空的第一个请求)中执行某些操作并将其传递给整个解析器,则存储非常有用。

【讨论】:

    【解决方案2】:

    好的,感谢@cyberwombat 的评论:

    除非您重新映射数据以便能够在一个请求中获取所有项目

    我能够弄清楚这一点。首先,我不得不稍微重构一下我的表。我将主键(哈希)更改为game_<uuid>,然后使用meta_<timestamp> 之类的排序键(范围)和player_<uuid> 之类的排序键引用游戏详细信息。

    一旦我这样做了,我就可以使用这个解析器来查询并返回游戏详细信息以及具有此请求映射模板的所有玩家:

    {
        "version": "2017-02-28",
        "operation": "Query",
        "query" : {
            "expression" : "pk = :pk",
            "expressionValues" : {
                ":pk": { "S":  "$ctx.arguments.pk" }
            }
        }
    }
    

    上述查询返回 5 个项目(4 个玩家和游戏元数据)。然后我使用了这样的响应映射模板:

    #set($game = {})
    #set($players = [])
    #foreach($item in $ctx.result.items)
        #if($util.matches('meta_\d*', $item.sk))
            ## main game object
            #set($game = $item)
        #else
            ## player
            $util.qr($players.add($item))
        #end
    #end
    
    $util.qr($game.put("players", $players))
    $util.toJson($game)
    

    现在我有一个对 DynamoDB 的单一查询,并且没有 lambda 解析器...漂亮。

    【讨论】:

      猜你喜欢
      • 2021-07-18
      • 2020-02-03
      • 2019-10-14
      • 1970-01-01
      • 2018-11-25
      • 1970-01-01
      • 2018-12-15
      • 2013-02-17
      • 2019-02-12
      相关资源
      最近更新 更多