密钥模式中的属性数必须与属性定义中定义的属性数相匹配

时间:2015-06-16 11:15:43

标签: amazon-dynamodb dynamo-local

我正在尝试使用DynamoDB javascript shell创建一个简单的表,我得到了这个例外:


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

以下是我要创建的表格:


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

但是,如果我将第二个属性添加到keySchema,它可以正常工作。在工作台下面:


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

我不想将范围添加到密钥架构。知道怎么解决吗?

4 个答案:

答案 0 :(得分:164)

DynamoDB是无模式的(除了密钥架构)

也就是说,您需要在创建表时指定密钥架构(属性名称和类型)。好吧,您不需要指定任何非关键属性。您可以稍后放置具有任何属性的项目(当然必须包括键)。

documentation page开始,AttributeDefinitions定义为:

  

描述表和索引的键架构的属性数组。

创建表时,AttributeDefinitions字段仅用于哈希和/或范围键。在第一种情况下,只提供哈希键(数字1),同时提供2个AttributeDefinitions。这是异常的根本原因。

TL; DR 请勿在{{1​​}}中包含任何非关键属性定义。

答案 1 :(得分:13)

在“AttributeDefinitions”中使用非键属性时,必须将其用作索引,否则它将违反dynamodb的工作方式。见link

因此,如果您不打算将其用作索引或主键,则无需在“AttributeDefinitions”中放置非键属性。

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

    });

答案 2 :(得分:1)

我也遇到了这个问题,我会在这里发布我遇到的问题,以防其他人帮忙。

在我的CreateTableRequest中,我有一个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>
  //{                            
  //}
};

在表创建中注释掉这些行解决了我的问题。所以我想列表必须为空,而不是空。

答案 3 :(得分:1)

仅当您打算在 AttrubuteDefinitions 中使用属性时才在 KeySchema 中声明属性

当这些属性将用于 GlobalSecondaryIndexesLocalSecondaryIndexes

对于任何使用 yaml 文件的人:

示例 1:

假设您有 3 个属性 -> id、status、createdAt。 这里的 id 是 KeySchema

    AuctionsTable:
      Type: AWS::DynamoDB::Table
      Properties:
        TableName: AuctionsTable
        BillingMode: PAY_PER_REQUEST
        
        AttributeDefinitions:
          - AttributeName: id
            AttributeType: S

        KeySchema:
          - AttributeName: id 
            KeyType: HASH

示例 2:

对于相同的属性(即 id、status 和 createdAt),如果您还有 GlobalSecondaryIndexesLocalSecondaryIndexes,那么您的 yaml 文件如下所示:

AuctionsTable:
  Type: AWS::DynamoDB::Table
  Properties:
    TableName: AuctionsTable-${self:provider.stage}
    BillingMode: PAY_PER_REQUEST
    AttributeDefinitions:
      - AttributeName: id
        AttributeType: S
      - AttributeName: status
        AttributeType: S
      - AttributeName: endingAt
        AttributeType: S
    KeySchema:
      - AttributeName: id
        KeyType: HASH
    GlobalSecondaryIndexes:
      - IndexName: statusAndEndDate
        KeySchema:
          - AttributeName: status
            KeyType: HASH
          - AttributeName: endingAt
            KeyType: RANGE
        Projection:
          ProjectionType: ALL

我们在 AttributeDefinitions 中包含 status 和 createdId 只是因为我们有一个使用上述属性的 GlobalSecondaryIndex