DynamoDB запрашивает вторичный индекс, как определить индексы - PullRequest
0 голосов
/ 30 мая 2018

Я ходил по кругу и вокруг, и просто не ясно, что делать.

У меня есть простая таблица, где я хочу делать запросы к нескольким столбцам.Насколько я понимаю, это означает создание вторичного индекса для каждого столбца, к которому необходимо выполнить запрос.Я определил таблицу - используя Serverless Framework 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).

1 Ответ

0 голосов
/ 30 мая 2018

Причина, по которой он не работает, состоит в том, что ключи в локальном вторичном индексе должны иметь тот же ключ раздела, что и таблица.Так что в вашем случае ваши локальные вторичные индексы должны иметь messageId в качестве ключа HASH и room и userId в качестве 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 как часть запроса, так как это ключ раздела.Таким образом, вы не сможете сделать запрос, просто room и userId.Что вы, вероятно, хотите, это Глобальные вторичные индексы .В этом случае это будет работать:

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 вы получите только 1026 * - тогда вы получитезапросить таблицу с помощью messageIds, чтобы получить другие атрибуты.Возможно, вы захотите использовать другой ProjectionType в зависимости от того, какой у вас шаблон использования.

...