Dynamodb 稀疏索引实现

Dynamodb sparse indexes implementation

我是 dynamodb 的新手,遇到了 sparse indexes。我认为它们适合我的需要,但我不完全确定如何实施它们。在我的例子中,我有一个 table 和一个 Post 实体,它有以下字段,它看起来像这样:

post_id <string> | user_id <string> | tags <string[]> | public <boolean>| other post data attributes...

我需要做的查询是:

  1. 获取所有标记为public
  2. 的post
  3. 获取 posts 按标签筛选
  4. 获取所有 post 由用户过滤,包括 public 和不 public
  5. 获得一个post

对于获取所有 public post 的情况,我认为 稀疏索引 可以工作。我只能将 public 属性设置为标有 public 的实体。但是,查询看起来像什么?

我什至不确定我是否正确设置了数据库。我正在使用无服务器框架,这是我想出的,但不确定它是否好。

PostsDynamoDBTable:
      Type: 'AWS::DynamoDB::Table'
      Properties:
        AttributeDefinitions:
          - AttributeName: postId
            AttributeType: S
          - AttributeName: userId
            AttributeType: S
          - AttributeName: createdAt
            AttributeType: S
        KeySchema:
          - AttributeName: postId
            KeyType: HASH
          - AttributeName: userId
            KeyType: RANGE
        BillingMode: PAY_PER_REQUEST
        TableName: ${self:provider.environment.POSTS_TABLE}
        GlobalSecondaryIndexes:
          - IndexName: ${self:provider.environment.USER_ID_INDEX}
            KeySchema:
              - AttributeName: userId
                KeyType: HASH
              - AttributeName: public
                KeyType: RANGE
            Projection:
              ProjectionType: ALL

稀疏索引可以工作如果您只想要属性的一个子集,您会想要使用ProjectionType: INCLUDES将non-key属性包含到稀疏索引(在你的例子中:public 属性)。请务必注意,在对稀疏索引的查询中您可以访问的唯一属性是您显式包含的属性。

首先,您需要在属性定义中声明那些 public 属性。

例如,public 属性之一是 userName。 您要添加:

 - AttributeName: userName
   AttributeType: S

然后,在 GlobalSecondaryIndexes 块中:

GlobalSecondaryIndexes:
  - IndexName: byUserIdAndPublic // You can name this whatever you'd like
    KeySchema:
      - AttributeName: userId
        KeyType: HASH
      - AttributeName: public
        KeyType: RANGE
      Projection:
        NonKeyAttributes:
        - userName
      ProjectionType: INCLUDE

然后您只需专门查询该索引 - 在响应中,您将取回用户名(不需要特殊的查询更改,除非指定使用该索引)。

如果每个 post 都需要 all 属性,则需要使用 ProjectionType: ALL,(然后只需删除 NonKeyAttributes位)

这是一个示例 nodejs 方法,它将通过 public 过滤 posts(public 是传递给该方法的布尔值):

const listByUserIdAndPublic = async (userId, public) => {
  const params = {
    TableName: tableName,
    IndexName: 'byUserIdAndPublic',
    KeyConditionExpression: '#public = :public AND #userId = :userId',
    ExpressionAttributeNames: {
      '#userId': 'userId',
      '#public': 'public'
    },
    ExpressionAttributeValues: {
      ':public': public,
      ':userId': userId
    },
  };
  const response = await documentClient.query(params).promise();
  return response.Items;
};

根据您的问题:

Get all posts that are marked public

我想你会想要使用完整索引 (ProjectionType: ALL),因为我想你希望 post 的所有属性都被索引。