DynamoDB查询二级索引,如何定义索引 [英] DynamoDB queries on secondary index, how to define the indexes

查看:76
本文介绍了DynamoDB查询二级索引,如何定义索引的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在四处走动,但不清楚该怎么做.

I've been going around and around this and it's just not clear what to do.

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

I have a simple table where I want to make queries against several columns. As I understand it, that means creating a secondary index for each column there is to query against. I've defined the table -- using the Serverless framework serverless.yml -- and am getting a variety of strange error messages.

当前的 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服务-因此我想查询房间,用户等的条目.

It's meant to be something like a Slack service - and therefore I want to query for entries from a room, by a user, and so forth.

根据我已经找到的文档,此定义很有意义.我们应该为索引中使用的列声明属性,而我已经这样做了.KeySchema-我实际上只需要messageId字段,但是错误消息表明它需要RANGE索引,因此我将userId字段添加到KeySchema中只是为了关闭它.根据我已经找到的文档,二级索引字段看起来正确.

This definition makes sense going by the documentation I've been able to find. One is supposed to declare Attributes for the columns used in indexes, and I've done so. The KeySchema - I really only need the messageId field, but an error message indicated it needed a RANGE index, so I added the userId field to the KeySchema just to shut that up. The secondary index fields look right based on the documentation I've been able to find.

使用此定义,尝试使用 lessserver deploy

With this definition I'm getting this error when trying to deploy using serverless deploy

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

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

I have tried several variations and gotten other strange errors as well. What follows is a few, but I don't remember what the corresponding changes were to the definition.

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).

推荐答案

不起作用的原因是,本地二级索引中的键必须具有与表相同的分区键.因此,在您的情况下,您的本地二级索引必须将 messageId 作为其 HASH 键,并将 room userId 作为<它们各自索引上的code> RANGE 键.并且由于您的表已经由(messageId,userId)键控,因此您不需要 userId

The reason it isn't working is that the keys in a Local Secondary Index must have the same partition key as the table. So in your case, your Local Secondary Indexes must have messageId as its HASH key and room and userId as RANGE keys on their respective indexes. And since your table is already keyed by (messageId, userId) then you don't need the userId Local Secondary Index.

此设置在技术上可以正常工作:

This setup would technically work:

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 作为查询的一部分来查询表,因为它是分区键.因此,您将无法仅通过 room userId 进行查询.您可能想要的是全球二级索引.在这种情况下,这将起作用:

However if what you want to do is query by rooms and users, then you probably want to go with a different table design. What you are trying to do would end up requiring you to always query the table using the messageId as part of the query since it is the partition key. So you wouldn't be able to query by just room and userId. What you probably want are Global Secondary Indexes. In that case, this would work:

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 意味着当您查询 roomIndex userIndex 时,您得到的只是 messageIds -然后,您必须使用 messageIds 重新查询表以获取其他属性.您可能要根据使用方式使用其他 ProjectionType .

Note that making your ProjectionType: KEYS_ONLY means when you query roomIndex or userIndex what you would get back is just messageIds - you would then have to requery the table with the messageIds to get other attributes. You might want to use a different ProjectionType depending on what your usage pattern is.

这篇关于DynamoDB查询二级索引,如何定义索引的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆