Como criar a tabela dynamodb usando serverless.yml e excluir os itens dela usando python boto3?

Sep 25 2020

Criei a tabela dynamodb usando serverless.yml como abaixo:

resources:
  Resources:
    myTable:
      Type: AWS::DynamoDB::Table
      DeletionPolicy: Retain
      Properties:
        TableName: myTable
        AttributeDefinitions:
          - AttributeName: id
            AttributeType: S
          - AttributeName: firstname
            AttributeType: S
          - AttributeName: lastname
            AttributeType: S
        KeySchema:
          - AttributeName: id
            KeyType: HASH
          - AttributeName: firstname
            KeyType: RANGE
        BillingMode: PAY_PER_REQUEST
        SSESpecification:
          SSEEnabled: true

Mas eu tenho este problema:

Ocorreu um erro: myTable - um ou mais valores de parâmetro eram inválidos: o número de atributos em KeySchema não corresponde exatamente ao número de atributos definidos em AttributeDefinitions (Serviço: AmazonDynamoDBv2; Código de status: 400; Código de erro: ValidationException; ID de solicitação: PEI9OT7E72HQN4N5MQUOIUQ18JVV4KUAQNSA66 : nulo).

Você poderia me ajudar a criar a tabela dynamodb usando serverless.yml? E como posso excluir os itens cujo primeiro nome é "Primeiro" nesta tabela usando python boto3?

Respostas

2 Marcin Oct 14 2020 at 06:06

Se você quiser manter o seu KeySchemavocê tem que deixar cair lastname a partir de AttributeDefinitions:

Resources:
  myTable:
    Type: AWS::DynamoDB::Table
    DeletionPolicy: Retain
    Properties:
      TableName: myTable
      AttributeDefinitions:
        - AttributeName: id
          AttributeType: S
        - AttributeName: firstname
          AttributeType: S
      KeySchema:
        - AttributeName: id
          KeyType: HASH
        - AttributeName: firstname
          KeyType: RANGE
      BillingMode: PAY_PER_REQUEST
      SSESpecification:
        SSEEnabled: true

Mas se você quiser manter lastname, você pode definir o índice secundário local para sua tabela:

Resources:
  myTable:
    Type: AWS::DynamoDB::Table
    DeletionPolicy: Retain
    Properties:
      TableName: myTable
      AttributeDefinitions:
        - AttributeName: id
          AttributeType: S
        - AttributeName: firstname
          AttributeType: S
        - AttributeName: lastname
          AttributeType: S
      KeySchema:
        - AttributeName: id
          KeyType: HASH
        - AttributeName: firstname
          KeyType: RANGE
      LocalSecondaryIndexes:
        - IndexName: by-lastname
          KeySchema: 
          - AttributeName: id
            KeyType: HASH
          - AttributeName: lastname
            KeyType: RANGE
          Projection: 
            ProjectionType: ALL
      BillingMode: PAY_PER_REQUEST
      SSESpecification:
        SSEEnabled: true

Com o acima, você pode classificar para lastnameusar o LSI, enquanto firstnameseria usado na tabela primária.

como posso excluir os itens cujo primeiro nome é "Primeiro" nesta tabela usando python boto3?

Você não pode fazer isso diretamente com ou sem boto3, a menos que queira fazer uma varredura , o que deve ser evitado porque pode ser caro e não é eficiente. A solução geral é definir índices secundários globais, onde firstnameseria a nova chave primária. Em seguida, você consultaria o GSI do firstnamede interesse para obter o iddo registro que deseja excluir. Se você tiver vários registros com o mesmo firstname, o que provavelmente será o caso, você obterá um número de registros de volta (as chaves primárias GSI não precisam ser exclusivas , ao contrário da tabela primária).

Tabela de exemplo com LSI e GSI:

Resources:
  myTable:
    Type: AWS::DynamoDB::Table
    DeletionPolicy: Retain
    Properties:
      TableName: myTable
      AttributeDefinitions:
        - AttributeName: id
          AttributeType: S
        - AttributeName: firstname
          AttributeType: S
        - AttributeName: lastname
          AttributeType: S
      KeySchema:
        - AttributeName: id
          KeyType: HASH
        - AttributeName: firstname
          KeyType: RANGE
      LocalSecondaryIndexes:
        - IndexName: by-lastname
          KeySchema: 
          - AttributeName: id
            KeyType: HASH
          - AttributeName: lastname
            KeyType: RANGE
          Projection: 
            ProjectionType: ALL
      GlobalSecondaryIndexes:
        - IndexName: firstname-gsi
          KeySchema: 
            - AttributeName: firstname
              KeyType: HASH
          Projection: 
            ProjectionType: ALL
          #ProvisionedThroughput: 
          #  ProvisionedThroughput        
      BillingMode: PAY_PER_REQUEST
      SSESpecification:
        SSEEnabled: true
PubuduJayawardana Sep 25 2020 at 18:55

A razão é que todos os seus AttributeNames em AttributeDefinitionsdevem ser incluídos KeySchematambém. Eu posso ver que o lastnameatributo está faltando lá.