首页 > 解决方案 > 创建 DynamoDB GlobalSecondaryIndex 以仅包含具有特定属性的项目

问题描述

我正在按照单表设计原则创建一个 DynamoDB 表。

我的基表定义如下所示(无服务器框架):

DataTable:
  Type: AWS::DynamoDB::Table
  Properties:
    TableName: ${self:provider.environment.DATA_TABLE}
    AttributeDefinitions:
      - AttributeName: pk
        AttributeType: S
      - AttributeName: sk
        AttributeType: S
    KeySchema:
      - AttributeName: pk
        KeyType: HASH
      - AttributeName: sk
        KeyType: RANGE

目前在表中是GameGamePlayer对象,其中 aGame看起来像这样:

{
    "pk": "GAME#game1", 
    "sk": "#META#game1", 
    "numPlayers": 2, 
    ... 
}

GamePlayer看起来像这样:

{
    "pk": "GAME#game1", 
    "sk": "PLAYER#player1", 
    "score":10, 
    ... 
}
{
    "pk": "GAME#game1", 
    "sk": "PLAYER#player2", 
    "score":20, 
    ... 
}

我想创建一个倒排索引来按玩家搜索游戏,所以我更新了我的表声明以添加一个 GlobalSecondaryIndex:

DataTable:
  Type: AWS::DynamoDB::Table
  Properties:
    TableName: ${self:provider.environment.DATA_TABLE}
    AttributeDefinitions:
      - AttributeName: pk
        AttributeType: S
      - AttributeName: sk
        AttributeType: S
    KeySchema:
      - AttributeName: pk
        KeyType: HASH
      - AttributeName: sk
        KeyType: RANGE
    GlobalSecondaryIndexes:
      - # for finding games by player
        IndexName: ${self:provider.environment.DATA_TABLE_PLAYER_GAME_INDEX}
        KeySchema:
          - AttributeName: sk
            KeyType: HASH
          - AttributeName: pk
            KeyType: RANGE
        Projection:
          NonKeyAttributes: 
            - score
          ProjectionType: "INCLUDE"

所以基本上是倒置的pksk我只想投影键和score属性,这就是我感兴趣的全部。

在创建表后查看索引,很明显 Dynamo 包含了基表中的所有项目,并复制了score它存在的项目。

如果我将 设置scoreHASHorRANGE键,DynamoDB 只会在索引中包含具有该属性的项目。

pk鉴于此表中的所有项目都将具有一个和一个sk属性,因此是否也将包含在倒排索引中,是否有一种方法可以使第三属性具有相同的行为?

编辑

如果问题不清楚,请道歉。我会尽量准确一点。

我正在开发一个使用 DynamoDB 作为后端的游戏。我正在遵循此处概述的 One Table 设计模式:https ://www.youtube.com/watch?v=7VQs9L-G8O4

基本上,由于表中可以有许多不同类型的对象,分区键和排序键是通用的,在这种情况下pksk.

目前,在我的表中,我可以存储 3 种类型的对象:GameGamePlayerUser.

GameUser,因为顶级对象遵循模式 where pkis a unique id and skis just#META#...和它们的 id。当 aUser加入 aGame时,我创建 a GamePlayer,其中pk是游戏的 id,并且skPLAYER#...和 的 id User

这让我可以使用 and的 id在一个查询中搜索和Game所有关联(如果不清楚,请参阅视频以了解这一点)。GamePlayerspkGamesk between #META and Player$

由于表中有许多不同的对象,显然某些属性存在于一个对象上但不存在于其他对象上——例如,一个属性email只存在于UserscoreGamePlayer

视频中提到的模式之一是“倒置”索引的概念。如在默认情况下,使用 id 的 a Game,我可以获得Game和 all GamePlayers。倒排索引是sk作为分区键和pk排序键的 GlobalSecondaryIndex。这意味着,给定 a 的 id User,我现在可以找到GamePlayer与该关联的所有对象User

为了不复制我的整个数据库,我只想包含 的score属性GamePlayer,所以我创建了我的倒排索引并将其设置scoreNonKeyAttribute要包含的。但是,由于数据库中的每个对象都包含pksk属性,因此 Dynamo 会复制每个对象,并将score属性设置undefined为大多数(因为这些项目上不存在该属性)。

Users例如,如果我想创建一个 GlobalSecondaryIndexemail作为分区或排序键,那么 Dynamo 只会用User对象填充索引(即全局表中可能有 5 个项目,但索引中只有 1 个)。

所以我的问题是,是否可以保留我的倒排索引,但只包括那些具有score属性的项目?

样品表:

PK sk 玩家人数 分数 电子邮件
游戏#game1 #META#game1 2
游戏#game1 玩家#player1 10
游戏#game1 播放器#player2 20
用户#player1 #META#player1 我@email.com

标签: amazon-web-servicesamazon-dynamodbserverlessaws-serverless

解决方案


推荐阅读