【问题标题】:DynamoDB queries on secondary index, how to define the indexesDynamoDB 查询二级索引,如何定义索引
【发布时间】:2018-11-08 21:39:02
【问题描述】:

我一直在这个问题上转来转去,只是不清楚该怎么做。

我有一个简单的表,我想在其中对几列进行查询。据我了解,这意味着为要查询的每一列创建一个二级索引。我已经定义了表——使用无服务器框架serverless.yml——并且收到了各种奇怪的错误消息。

当前serverless.yml定义为:

resources:
  Resources:
    MessagesDynamoDBTable:
      Type: 'AWS::DynamoDB::Table'
      Properties:
        AttributeDefinitions:
          - AttributeName: messageId
            AttributeType: S
          - AttributeName: room
            AttributeType: S
          - AttributeName: userId
            AttributeType: S
        KeySchema:
          - AttributeName: messageId
            KeyType: HASH
          - AttributeName: userId
            KeyType: RANGE
        LocalSecondaryIndexes:
          - IndexName: roomIndex
            KeySchema: 
              - AttributeName: room
                KeyType: HASH
            Projection: 
              ProjectionType: "KEYS_ONLY"
          - IndexName: userId
            KeySchema: 
              - AttributeName: userId
                KeyType: HASH
            Projection: 
              ProjectionType: "KEYS_ONLY"
        ProvisionedThroughput:
          ReadCapacityUnits: 1
          WriteCapacityUnits: 1
        TableName: ${self:custom.tableName}

它类似于 Slack 服务 - 因此我想查询来自房间、用户等的条目。

根据我能找到的文档,这个定义是有意义的。一个应该为索引中使用的列声明属性,我已经这样做了。 KeySchema - 我真的只需要 messageId 字段,但是一条错误消息表明它需要一个 RANGE 索引,所以我将 userId 字段添加到 KeySchema 只是为了关闭它。根据我找到的文档,二级索引字段看起来很正确。

根据这个定义,我在尝试使用 serverless deploy 进行部署时遇到此错误

An error occurred: MessagesDynamoDBTable - Property AttributeDefinitions is inconsistent 
with the KeySchema of the table and the secondary indexes.

我尝试了几种变体,也遇到了其他奇怪的错误。以下是一些,但我不记得对定义的相应更改。

An error occurred: MessagesDynamoDBTable - One or more parameter values were invalid: 
Index KeySchema does not have a range key for index: userId (Service: AmazonDynamoDBv2; Status Code: 400;
Error Code: ValidationException; Request ID: 1KFA2IMASC12HRLLDPG753CU63VV4KQNSO5AEMVJF66Q9ASUAAJG).

An error occurred: MessagesDynamoDBTable - 1 validation error detected: Value '[com.amazonaws.dynamodb.v20120810.KeySchemaElement@aa4cdc91, 
com.amazonaws.dynamodb.v20120810.KeySchemaElement@d2cd6f64, com.amazonaws.dynamodb.v20120810.KeySchemaElement@4d7c1f9, 
com.amazonaws.dynamodb.v20120810.KeySchemaElement@d2cd6f64]' at 'keySchema' failed to satisfy constraint: Member must have length less
 than or equal to 2 (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException; Request ID: BOVVBQ1F35VA18CCF3L5MSKS1FVV4KQNSO5AEMVJF66Q9ASUAAJG).

An error occurred: MessagesDynamoDBTable - Property AttributeDefinitions is inconsistent with the KeySchema 
of the table and the secondary indexes.

An error occurred: MessagesDynamoDBTable - One or more parameter values were invalid: Index KeySchema does not have a range key for index:
 userIdIndex (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException; Request ID: KFS63VSPKDUC60DV6U2V47UP27VV4KQNSO5AEMVJF66Q9ASUAAJG).

An error occurred: MessagesDynamoDBTable - One or more parameter values were invalid: Table KeySchema does not have a range key,
 which is required when specifying a LocalSecondaryIndex (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException; Request ID: 86Q2JSPM6Q9UPNIEOVHALLIIQJVV4KQNSO5AEMVJF66Q9ASUAAJG).

【问题讨论】:

    标签: amazon-dynamodb serverless-framework dynamodb-queries amazon-dynamodb-index


    【解决方案1】:

    它不起作用的原因是本地二级索引中的键必须与表具有相同的分区键。因此,在您的情况下,您的本地二级索引必须将 messageId 作为其 HASH 键,并将 roomuserId 作为各自索引上的 RANGE 键。由于您的表已经由(messageId, userId) 键入,因此您不需要userId Local Secondary Index

    此设置在技术上可行:

    MessagesDynamoDBTable:
      Type: AWS::DynamoDB::Table
      Properties:
        AttributeDefinitions:
          - AttributeName: messageId
            AttributeType: S
          - AttributeName: room
            AttributeType: S
          - AttributeName: userId
            AttributeType: S
        KeySchema:
          - AttributeName: messageId
            KeyType: HASH
          - AttributeName: userId
            KeyType: RANGE
        LocalSecondaryIndexes:
          - IndexName: roomIndex
            KeySchema:
              - AttributeName: messageId
                KeyType: HASH
              - AttributeName: room
                KeyType: RANGE
            Projection:
              ProjectionType: KEYS_ONLY
        ProvisionedThroughput:
          ReadCapacityUnits: 1
          WriteCapacityUnits: 1
        TableName: ${self:custom.tableName}
    

    但是,如果您想要按房间和用户进行查询,那么您可能希望采用不同的表格设计。您尝试执行的操作最终会要求您始终使用 messageId 作为查询的一部分来查询表,因为它是分区键。因此,您将无法仅通过 roomuserId 进行查询。你可能想要的是Global Secondary Indexes。在这种情况下,这将起作用:

    MessagesDynamoDBTable:
      Type: AWS::DynamoDB::Table
      Properties:
        AttributeDefinitions:
          - AttributeName: messageId
            AttributeType: S
          - AttributeName: room
            AttributeType: S
          - AttributeName: userId
            AttributeType: S
        KeySchema:
          - AttributeName: messageId
            KeyType: HASH
        GlobalSecondaryIndexes:
          - IndexName: roomIndex
            KeySchema:
              - AttributeName: room
                KeyType: HASH
            Projection:
              ProjectionType: KEYS_ONLY
            ProvisionedThroughput:
              ReadCapacityUnits: 1
              WriteCapacityUnits: 1
          - IndexName: userIndex
            KeySchema:
              - AttributeName: userId
                KeyType: HASH
            Projection:
              ProjectionType: KEYS_ONLY
            ProvisionedThroughput:
              ReadCapacityUnits: 1
              WriteCapacityUnits: 1
        ProvisionedThroughput:
          ReadCapacityUnits: 1
          WriteCapacityUnits: 1
        TableName: ${self:custom.tableName}
    

    请注意,创建ProjectionType: KEYS_ONLY 意味着当您查询roomIndexuserIndex 时,您将得到的只是messageIds - 然后您必须使用messageIds 重新查询表以获取其他属性。根据您的使用模式,您可能希望使用不同的 ProjectionType

    【讨论】:

    • 这很有帮助。我非常感谢你。我还有一些问题要解决,但它让我走得更远。
    • 谢谢你,你帮我清理了很多东西!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    相关资源
    最近更新 更多