Как реализовать глобальный вторичный индекс DynamoDB с инфраструктурой в виде кода в CloudFormation - PullRequest
0 голосов
/ 14 июня 2019

Я работаю над внедрением GSI в CloudFormation с использованием инфраструктуры в виде кода. Все, что я хочу сделать, это использовать эту таблицу, чтобы вести подсчет записей в главной таблице DynamoTable. Вот как выглядит основная сказка:

Resources:
  CaseRecords:
    Type: AWS::DynamoDB::Table
    Properties:
      TableName: ${self:custom.tableName}
      BillingMode: PAY_PER_REQUEST
      AttributeDefinitions:
        - AttributeName: userId
          AttributeType: S
        - AttributeName: caseRecordId
          AttributeType: S
      KeySchema:
        - AttributeName: userId
          KeyType: HASH
        - AttributeName: caseRecordId
          KeyType: RANGE

Мне не нужны ключи из исходной таблицы, и все, что мне нужно, - это создать новый ключ HASH для нового GSI, который сообщит мне, из какой таблицы получен подсчет, за которым я следил, то есть из таблицы выше.

Ниже показано, как я пытался реализовать GSI:

# Implement a GSI to handle item count totals
      GlobalSecondaryIndexes:
          - IndexName: gsiCaseCountTable
            KeySchema: 
              - AttributeName: table-name
                KeyType: HASH
            ProvisionedThroughput:
              ReadCapacityUnits: 5
              WriteCapacityUnits: 5

Однако я получаю следующую ошибку:

An error occurred: CaseRecords - Property Projection cannot be empty..

Когда я включаю ПРОЕКЦИЮ, в которой находился, только с userId из исходной таблицы, чтобы просто отслеживать количество записей в исходной таблице на пользователя, я пытаюсь сделать следующее:

 Implement a GSI to handle item count totals
      GlobalSecondaryIndexes:
      - IndexName: gsiCaseCountTable
        KeySchema:
        - AttributeName: table-name
          KeyType: HASH
        Projection:
          NonKeyAttributes:
          - userId
          ProjectionType: INCLUDE
        ProvisionedThroughput:
          ReadCapacityUnits: 5
          WriteCapacityUnits: 5

Однако это также возвращает ошибку:

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

Как правильно реализовать Глобальный вторичный индекс в Динамо, используя шаблон CloudFormation, чтобы я мог записать количество записей в исходной таблице ????

Спасибо.

UPDATE

В случае, если кому-то интересно, вот как я смог его развернуть. Это не идеальное решение, но оно позволяет мне отслеживать и подсчитывать записи в таблице элементов:

# NOTE: DynamoDB Serverless Configuration
# NoSQL Table for CaseRecord DB

Resources:
  CaseRecords:
    Type: AWS::DynamoDB::Table
    Properties:
      TableName: ${self:custom.tableName}
      BillingMode: PAY_PER_REQUEST
      AttributeDefinitions:
        - AttributeName: userId
          AttributeType: S
        - AttributeName: caseRecordId
          AttributeType: S
      KeySchema:
        - AttributeName: userId
          KeyType: HASH
        - AttributeName: caseRecordId
          KeyType: RANGE
      # Set the capacity based on the stage
      # ProvisionedThroughput:
        # ReadCapacityUnits: ${self:custom.tableThroughput}
        # WriteCapacityUnits: ${self:custom.tableThroughput}
      # Implement a GSI to handle item count totals
      GlobalSecondaryIndexes:
      - IndexName: gsiCaseCountTable
        KeySchema:
        - AttributeName: userId
          KeyType: HASH
        Projection:
          ProjectionType: KEYS_ONLY

ОБНОВЛЕНИЕ № 2 - СБОЙ

Основываясь на информации, предоставленной @Pedro Arantes ниже, я пытаюсь реализовать GSI с определениями атрибутов, которые я хочу использовать. Это тоже однако терпит неудачу. Ниже приведена реализация, а вот ссылка на документ AWS, который я использовал: AWS GSI Doc , а вот сбойная реализация:

Resources:
  CaseRecords:
    Type: AWS::DynamoDB::Table
    Properties:
      TableName: ${self:custom.tableName}
      BillingMode: PAY_PER_REQUEST
      AttributeDefinitions:
        - AttributeName: userId
          AttributeType: S
        - AttributeName: caseRecordId
          AttributeType: S
        - AttributeName: table-name
          AttributeType: S
        - AttributeName: count
          AttributeType: N
      KeySchema:
        - AttributeName: userId
          KeyType: HASH
        - AttributeName: caseRecordId
          KeyType: RANGE
      # Set the capacity based on the stage
      # ProvisionedThroughput:
        # ReadCapacityUnits: ${self:custom.tableThroughput}
        # WriteCapacityUnits: ${self:custom.tableThroughput}
      # Implement a GSI to handle item count totals
      GlobalSecondaryIndexes:
      - IndexName: gsiCaseCountTable
        KeySchema:
        - AttributeName: table-name
          KeyType: HASH
        Projection: 
          NonKeyAttributes: 
            - userId
            - count
          ProjectionType: INCLUDE

Как мне заставить это работать только с NonKeyAttributes, который я объявил в AttributeDefinitions ???

1 Ответ

2 голосов
/ 14 июня 2019

Вам необходимо добавить table-name в AttributeDefinitions свойство. От документов :

AttributeDefinitions

Список атрибутов, которые описывают схему ключей для таблицы и индексов. Дубликаты разрешены.

Таким образом, даже если вы не используете какой-либо атрибут в исходной таблице, вы должны заявить, что сможете использовать его в GSI.

ОБНОВЛЕНИЕ № 2 - СБОЙ

Вы используете атрибуты ключей userId и count, которые вы определили в AttributeDefinitions как NonKeyAttributes (но они являются атрибутами ключей) в Projection. Вам не нужно добавлять их, потому что они автоматически проецируются. От документов :

AWS :: DynamoDB :: Проекция таблицы

Представляет атрибуты, которые копируются (проецируются) из таблицы в индекс. Это в дополнение к атрибутам первичного ключа и атрибутам индексного ключа, которые проецируются автоматически.

ФИНАЛЬНЫЙ ШАБЛОН

Resources:
  CaseRecords:
    Type: AWS::DynamoDB::Table
    Properties:
      TableName: ${self:custom.tableName}
      BillingMode: PAY_PER_REQUEST
      AttributeDefinitions:
        - AttributeName: userId
          AttributeType: S
        - AttributeName: caseRecordId
          AttributeType: S
        - AttributeName: table-name
          AttributeType: S
      KeySchema:
        - AttributeName: userId
          KeyType: HASH
        - AttributeName: caseRecordId
          KeyType: RANGE
      # Set the capacity based on the stage
      # ProvisionedThroughput:
      # ReadCapacityUnits: ${self:custom.tableThroughput}
      # WriteCapacityUnits: ${self:custom.tableThroughput}
      # Implement a GSI to handle item count totals
      GlobalSecondaryIndexes:
        - IndexName: gsiCaseCountTable
          KeySchema:
            - AttributeName: table-name
              KeyType: HASH
          Projection:
            NonKeyAttributes:
              - count
            ProjectionType: INCLUDE

Вопросы:

  1. count не должно быть включено AttributeDefinitions, потому что вы не используете его в качестве ключа.

  2. Вам не нужно добавлять userId в Projection, потому что это будет проект автоматически, так как он определен в AttributeDefinitions.

...