El número de atributos en el esquema de claves debe coincidir con el número de atributos definidos en las definiciones de atributos

107

Estoy tratando de crear una tabla simple usando el shell javascript de DynamoDB y obtengo esta excepción:


    {   
    "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 
    }

A continuación se muestra la tabla que estoy tratando de crear:


    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); 
    });

Sin embargo, si agrego el segundo atributo a keySchema, funciona bien. Debajo de la mesa de trabajo:


    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); 
    });

No quiero agregar el rango al esquema de claves. ¿Alguna idea de cómo arreglarlo?

NAbbas
fuente
¿Esto solo sucede contra DynamoDBLocal? ¿Qué sucede cuando intenta hacer lo mismo contra el servicio real?
mkobit
Todavía no tengo una cuenta de AWS, por lo que no pude probarla con el servicio real. Estoy usando la última versión de DynamoDB local (dynamodb_local_2015-04-27_1.0).
NAbbas
1
Estoy experimentando el mismo comportamiento con dynamodb_local_2016-04-19
Chris
2
No importa, TL; DR de Mingliang lo dice todo.
Chris

Respuestas:

227

DynamoDB no tiene esquema (excepto el esquema de clave)

Es decir, necesita especificar el esquema de clave (nombre y tipo de atributo) cuando crea la tabla. Bueno, no es necesario que especifique ningún atributo que no sea clave. Puedes poner un artículo con cualquier atributo más adelante (debes incluir las claves por supuesto).

Desde la página de documentación , AttributeDefinitionsse define como:

Matriz de atributos que describen el esquema de claves de la tabla y los índices.

Cuando crea una tabla, el AttributeDefinitionscampo se usa solo para las claves hash y / o de rango. En su primer caso, solo hay una clave hash (número 1) mientras proporciona 2 AttributeDefinitions. Ésta es la causa raíz de la excepción.

TL; DR No incluya definiciones de atributos que no sean clave en AttributeDefinitions.

Mingliang Liu
fuente
10
con una excepción, creo, el atributo no clave debe estar en AttributeDefinitionssi esa clave se usará como clave hasho rangeen el índice
Srle
23

Cuando usa un atributo que no es clave en at "AttributeDefinitions", debe usarlo como índice; de ​​lo contrario, va en contra del funcionamiento de DynamoDB. Vea el enlace .

Por lo tanto, no es necesario colocar un atributo que no sea de clave "AttributeDefinitions"si no lo va a usar como índice o clave principal.

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
fuente
2

También tuve este problema y publicaré aquí lo que me salió mal en caso de que ayude a otra persona.

En mi CreateTableRequest, tenía una matriz vacía para 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 estas líneas en la creación de la tabla resolvió mi problema. Así que supongo que la lista debe estar nullvacía.

NickBeaugié
fuente