O número de atributos no esquema de chave deve corresponder ao número de atributos definidos nas definições de atributo

106

Estou tentando criar uma tabela simples usando o shell javascript do DynamoDB e estou recebendo esta exceção:


    {   
    "message": "The number of attributes in key schema must match the number of attributes defined in attribute definitions.",
    "code": "ValidationException",
    "time": "2015-06-16T10:24:23.319Z",
    "statusCode": 400,
    "retryable": false 
    }

Abaixo está a tabela que estou tentando criar:


    var params = {
        TableName: 'table_name',
        KeySchema: [ 
            { 
                AttributeName: 'hash_key_attribute_name',
                KeyType: 'HASH',
            },

        ],
        AttributeDefinitions: [ 
            {
                AttributeName: 'hash_key_attribute_name',
                AttributeType: 'S', 
            },
            {
                AttributeName: 'attribute_name_1',
                AttributeType: 'S', 
            }
        ],
        ProvisionedThroughput: { 
            ReadCapacityUnits: 1, 
            WriteCapacityUnits: 1, 
        },


    };
    dynamodb.createTable(params, function(err, data) {
        if (err) print(err); 
        else print(data); 
    });

No entanto, se eu adicionar o segundo atributo ao keySchema, ele funcionará bem. Abaixo da mesa de trabalho:


    var params = {
        TableName: 'table_name',
        KeySchema: [ 
            { 
                AttributeName: 'hash_key_attribute_name',
                KeyType: 'HASH',
            },
            { 
                AttributeName: 'attribute_name_1', 
                KeyType: 'RANGE', 
            }

        ],
        AttributeDefinitions: [ 
            {
                AttributeName: 'hash_key_attribute_name',
                AttributeType: 'S', 
            },
            {
                AttributeName: 'attribute_name_1',
                AttributeType: 'S', 
            }
        ],
        ProvisionedThroughput: { 
            ReadCapacityUnits: 1, 
            WriteCapacityUnits: 1, 
        },


    };
    dynamodb.createTable(params, function(err, data) {
        if (err) print(err); 
        else print(data); 
    });

Não quero adicionar o intervalo ao esquema de chave. Alguma idéia de como consertar isso?

NAbbas
fonte
Isso só acontece contra o DynamoDBLocal? O que acontece quando você tenta fazer a mesma coisa no serviço real?
mkobit
Ainda não tenho uma conta da AWS, então não pude testá-la em relação ao serviço real. Estou usando a versão mais recente do DynamoDB local (dynamodb_local_2015-04-27_1.0).
NAbbas
1
Estou tendo o mesmo comportamento com dynamodb_local_2016-04-19
Chris
2
Deixa pra lá, TL de Mingliang; DR diz tudo.
Chris

Respostas:

226

DynamoDB não tem esquema (exceto o esquema chave)

Ou seja, você precisa especificar o esquema de chave (nome e tipo do atributo) ao criar a tabela. Bem, você não precisa especificar nenhum atributo não-chave. Você pode colocar um item com qualquer atributo posteriormente (deve incluir as chaves, é claro).

Na página de documentação , o AttributeDefinitionsé definido como:

Uma matriz de atributos que descreve o esquema principal da tabela e dos índices.

Quando você cria uma tabela, o AttributeDefinitionscampo é usado apenas para as chaves hash e / ou de intervalo. Em seu primeiro caso, há apenas a chave hash (número 1) enquanto você fornece 2 Definições de atributo. Essa é a causa raiz da exceção.

TL; DR Não inclua nenhuma definição de atributo não-chave em AttributeDefinitions.

Mingliang Liu
fonte
10
com uma exceção, acredito, o atributo não-chave deve estar em AttributeDefinitionsse essa chave for usada como hashou rangechave no índice
Srle
22

Ao usar um atributo não-chave em em "AttributeDefinitions", você deve usá-lo como um índice, caso contrário, é contra a maneira como o DynamoDB funciona. Veja o link .

Portanto, não há necessidade de inserir um atributo não-chave "AttributeDefinitions"se não for usá-lo como índice ou chave primária.

var params = {
        TableName: 'table_name',
        KeySchema: [ // The type of of schema.  Must start with a HASH type, with an optional second RANGE.
            { // Required HASH type attribute
                AttributeName: 'UserId',
                KeyType: 'HASH',
            },
            { // Optional RANGE key type for HASH + RANGE tables
                AttributeName: 'RemindTime', 
                KeyType: 'RANGE', 
            }
        ],
        AttributeDefinitions: [ // The names and types of all primary and index key attributes only
            {
                AttributeName: 'UserId',
                AttributeType: 'S', // (S | N | B) for string, number, binary
            },
            {
                AttributeName: 'RemindTime',
                AttributeType: 'S', // (S | N | B) for string, number, binary
            },
            {
                AttributeName: 'AlarmId',
                AttributeType: 'S', // (S | N | B) for string, number, binary
            },
            // ... more attributes ...
        ],
        ProvisionedThroughput: { // required provisioned throughput for the table
            ReadCapacityUnits: 1, 
            WriteCapacityUnits: 1, 
        },
        LocalSecondaryIndexes: [ // optional (list of LocalSecondaryIndex)
            { 
                IndexName: 'index_UserId_AlarmId',
                KeySchema: [ 
                    { // Required HASH type attribute - must match the table's HASH key attribute name
                        AttributeName: 'UserId',
                        KeyType: 'HASH',
                    },
                    { // alternate RANGE key attribute for the secondary index
                        AttributeName: 'AlarmId', 
                        KeyType: 'RANGE', 
                    }
                ],
                Projection: { // required
                    ProjectionType: 'ALL', // (ALL | KEYS_ONLY | INCLUDE)
                },
            },
            // ... more local secondary indexes ...
        ],
    };
    dynamodb.createTable(params, function(err, data) {
        if (err) ppJson(err); // an error occurred
        else ppJson(data); // successful response
    });
Gabriel Wu
fonte
2

Eu também tive esse problema e postarei aqui o que deu errado para mim, caso ajude outra pessoa.

No meu CreateTableRequest, eu tinha um array vazio para o GlobalSecondaryIndexes.

CreateTableRequest createTableRequest = new CreateTableRequest
{
  TableName = TableName,
  ProvisionedThroughput = new ProvisionedThroughput { ReadCapacityUnits = 2, WriteCapacityUnits = 2 },
  KeySchema = new List<KeySchemaElement>
  {
     new KeySchemaElement
     {
        AttributeName = "Field1",
        KeyType = KeyType.HASH
     },
     new KeySchemaElement
     {
        AttributeName = "Field2",
        KeyType = KeyType.RANGE
     }
  },
  AttributeDefinitions = new List<AttributeDefinition>()
  {
     new AttributeDefinition
     {
         AttributeName = "Field1", 
         AttributeType = ScalarAttributeType.S
     },
     new AttributeDefinition
     {
        AttributeName = "Field2",
        AttributeType = ScalarAttributeType.S
     }
  },
  //GlobalSecondaryIndexes = new List<GlobalSecondaryIndex>
  //{                            
  //}
};

Comentar essas linhas na criação da tabela resolveu meu problema. Então eu acho que a lista tem que estar null, não vazia.

NickBeaugié
fonte