Dynamodb не может создавать таблицы

Я тестирую AWS DynamoDB на своем локальном компьютере, но не могу создавать таблицы с глобальными индексами и.

Я получаю следующий вывод, и я не уверен, почему. Я думаю, что добавляю хэш-ключ в таблицы и индексы, поэтому я не уверен, почему он жалуется?

Issuing CreateTable request for Users
Waiting for Users to be created...this may take a while...
Issuing CreateTable request for Contacts
CreateTable request failed for Contacts
No Hash Key specified in schema.  All Dynamo DB tables must have exactly one hash key (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException; Request ID: b2c826df-a6e6-4bc5-af60-ff6b6c3a0065)
Issuing CreateTable request for Messages
CreateTable request failed for Messages
No Hash Key specified in schema.  All Dynamo DB tables must have exactly one hash key (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException; Request ID: 2117d767-f87f-4147-bfee-cafce6cf0ad8)

Это мой код (я создаю 3 таблицы, 2 с глобальными индексами):

public class Main{

    AmazonDynamoDBClient client;
    static DynamoDB dynamoDB;

    static String users = "Users";
    static String contacts = "Contacts";
    static String messages = "Messages";


    public Main() throws Exception {

        client = new AmazonDynamoDBClient(new ProfileCredentialsProvider());
        client.setEndpoint("http://localhost:8000");
        dynamoDB = new DynamoDB(client);


        try {

            deleteTable(users);
            deleteTable(contacts);
            deleteTable(messages);

            createTable(users, 10L, 5L, "un", "S");
            createTable(contacts, 10L, 5L, "to", "S");
            createTable(messages, 10L, 5L, "fr", "S", "cr", "S");


        } catch (Exception e) {
            System.err.println("Program failed:");
            System.err.println(e.getMessage());
        }
        System.out.println("Success.");


    private static void deleteTable(String tableName) {
        Table table = dynamoDB.getTable(tableName);
        try {
            System.out.println("Issuing DeleteTable request for " + tableName);
            table.delete();
            System.out.println("Waiting for " + tableName
                    + " to be deleted...this may take a while...");
            table.waitForDelete();

        } catch (Exception e) {
            System.err.println("DeleteTable request failed for " + tableName);
            System.err.println(e.getMessage());
        }
    }


    private static void createTable(
            String tableName, long readCapacityUnits, long writeCapacityUnits,
            String hashKeyName, String hashKeyType) {

        createTable(tableName, readCapacityUnits, writeCapacityUnits,
                hashKeyName, hashKeyType, null, null);
    }

    private static void createTable(
            String tableName, long readCapacityUnits, long writeCapacityUnits,
            String hashKeyName, String hashKeyType,
            String rangeKeyName, String rangeKeyType) {

        try {

            ArrayList<KeySchemaElement> keySchema = new ArrayList<KeySchemaElement>();
            keySchema.add(new KeySchemaElement()
                    .withAttributeName(hashKeyName)
                    .withKeyType(KeyType.HASH));

            ArrayList<AttributeDefinition> attributeDefinitions = new ArrayList<AttributeDefinition>();
            attributeDefinitions.add(new AttributeDefinition()
                    .withAttributeName(hashKeyName)
                    .withAttributeType(hashKeyType));

            if (rangeKeyName != null) {
                keySchema.add(new KeySchemaElement()
                        .withAttributeName(rangeKeyName)
                        .withKeyType(KeyType.RANGE));
                attributeDefinitions.add(new AttributeDefinition()
                        .withAttributeName(rangeKeyName)
                        .withAttributeType(rangeKeyType));
            }

            CreateTableRequest request = new CreateTableRequest()
                    .withTableName(tableName)
                    .withKeySchema(keySchema)
                    .withProvisionedThroughput( new ProvisionedThroughput()
                            .withReadCapacityUnits(readCapacityUnits)
                            .withWriteCapacityUnits(writeCapacityUnits));



            if(contacts.equals(tableName)){

                // PrecipIndex
                GlobalSecondaryIndex contactsFromIndex = new GlobalSecondaryIndex()
                        .withIndexName("ContactsFromIndex")
                        .withProvisionedThroughput(new ProvisionedThroughput()
                                .withReadCapacityUnits((long) 10)
                                .withWriteCapacityUnits((long) 5))
                        .withProjection(new Projection().withProjectionType(ProjectionType.KEYS_ONLY));

                ArrayList<KeySchemaElement> indexKeySchema = new ArrayList<KeySchemaElement>();

                indexKeySchema.add(new KeySchemaElement()
                        .withAttributeName("fr")
                        .withKeyType("S"));
                indexKeySchema.add(new KeySchemaElement()
                        .withAttributeName("st")
                        .withKeyType("N"));

                contactsFromIndex.setKeySchema(indexKeySchema);
                request.withGlobalSecondaryIndexes(contactsFromIndex);

            }


            if(messages.equals(tableName)){

                // PrecipIndex
                GlobalSecondaryIndex messagesFromIndex = new GlobalSecondaryIndex()
                        .withIndexName("messagesFromIndex")
                        .withProvisionedThroughput(new ProvisionedThroughput()
                                .withReadCapacityUnits((long) 10)
                                .withWriteCapacityUnits((long) 5))
                        .withProjection(new Projection().withProjectionType(ProjectionType.INCLUDE)
                                .withNonKeyAttributes("mg"));

                ArrayList<KeySchemaElement> indexKeySchema = new ArrayList<KeySchemaElement>();

                indexKeySchema.add(new KeySchemaElement()
                        .withAttributeName("to")
                        .withKeyType("S"));
                indexKeySchema.add(new KeySchemaElement()
                        .withAttributeName("cr")
                        .withKeyType("N"));

                messagesFromIndex.setKeySchema(indexKeySchema);
                request.withGlobalSecondaryIndexes(messagesFromIndex);

            }


            request.setAttributeDefinitions(attributeDefinitions);

            System.out.println("Issuing CreateTable request for " + tableName);
            Table table = dynamoDB.createTable(request);
            System.out.println("Waiting for " + tableName
                    + " to be created...this may take a while...");
            table.waitForActive();

        } catch (Exception e) {
            System.err.println("CreateTable request failed for " + tableName);
            System.err.println(e.getMessage());
        }
    }

}

ОБНОВЛЕНО: сообщение об ошибке "Не может быть двух атрибутов с одинаковым именем" с новым кодом:

        client = new AmazonDynamoDBClient(new ProfileCredentialsProvider());
        client.setEndpoint("http://localhost:8000");
        dynamoDB = new DynamoDB(client);


        try {

            deleteTable(users);
            deleteTable(contacts);
            deleteTable(messages);

            createTable(users, 10L, 5L, "un", "S");
            createTable(contacts, 10L, 5L, "to", "S");
            createTable(messages, 10L, 5L, "fr", "S", "cr", "S");


        } catch (Exception e) {
            System.err.println("Program failed:");
            System.err.println(e.getMessage());
        }
        System.out.println("Success.");


    private static void deleteTable(String tableName) {
        Table table = dynamoDB.getTable(tableName);
        try {
            System.out.println("Issuing DeleteTable request for " + tableName);
            table.delete();
            System.out.println("Waiting for " + tableName
                    + " to be deleted...this may take a while...");
            table.waitForDelete();

        } catch (Exception e) {
            System.err.println("DeleteTable request failed for " + tableName);
            System.err.println(e.getMessage());
        }
    }


    private static void createTable(
            String tableName, long readCapacityUnits, long writeCapacityUnits,
            String hashKeyName, String hashKeyType) {

        createTable(tableName, readCapacityUnits, writeCapacityUnits,
                hashKeyName, hashKeyType, null, null);
    }

    private static void createTable(
            String tableName, long readCapacityUnits, long writeCapacityUnits,
            String hashKeyName, String hashKeyType,
            String rangeKeyName, String rangeKeyType) {

        try {

            ArrayList<KeySchemaElement> keySchema = new ArrayList<KeySchemaElement>();
            keySchema.add(new KeySchemaElement()
                    .withAttributeName(hashKeyName)
                    .withKeyType(KeyType.HASH));

            ArrayList<AttributeDefinition> attributeDefinitions = new ArrayList<AttributeDefinition>();
            attributeDefinitions.add(new AttributeDefinition()
                    .withAttributeName(hashKeyName)
                    .withAttributeType(hashKeyType));

            if (rangeKeyName != null) {
                keySchema.add(new KeySchemaElement()
                        .withAttributeName(rangeKeyName)
                        .withKeyType(KeyType.RANGE));
                attributeDefinitions.add(new AttributeDefinition()
                        .withAttributeName(rangeKeyName)
                        .withAttributeType(rangeKeyType));
            }

            CreateTableRequest request = new CreateTableRequest()
                    .withTableName(tableName)
                    .withKeySchema(keySchema)
                    .withProvisionedThroughput( new ProvisionedThroughput()
                            .withReadCapacityUnits(readCapacityUnits)
                            .withWriteCapacityUnits(writeCapacityUnits));



            if(contacts.equals(tableName)){
 attributeDefinitions.add(new AttributeDefinition().withAttributeName("fr").withAttributeType("S"));
                     attributeDefinitions.add(new AttributeDefinition().withAttributeName("st").withAttributeType("S"));
                // PrecipIndex
                GlobalSecondaryIndex contactsFromIndex = new GlobalSecondaryIndex()
                        .withIndexName("ContactsFromIndex")
                        .withProvisionedThroughput(new ProvisionedThroughput()
                                .withReadCapacityUnits((long) 10)
                                .withWriteCapacityUnits((long) 5))
                        .withProjection(new Projection().withProjectionType(ProjectionType.KEYS_ONLY));

                ArrayList<KeySchemaElement> indexKeySchema = new ArrayList<KeySchemaElement>();

                indexKeySchema.add(new KeySchemaElement()
                        .withAttributeName("fr")
                        .withKeyType(KeyType.HASH));
                indexKeySchema.add(new KeySchemaElement()
                        .withAttributeName("st")
                        .withKeyType(KeyType.RANGE));

                contactsFromIndex.setKeySchema(indexKeySchema);
                request.withGlobalSecondaryIndexes(contactsFromIndex);

            }


            if(messages.equals(tableName)){
attributeDefinitions.add(new AttributeDefinition().withAttributeName("to").withAttributeType("S"));
                    attributeDefinitions.add(new AttributeDefinition().withAttributeName("cr").withAttributeType("N"));

                // PrecipIndex
                GlobalSecondaryIndex messagesFromIndex = new GlobalSecondaryIndex()
                        .withIndexName("messagesFromIndex")
                        .withProvisionedThroughput(new ProvisionedThroughput()
                                .withReadCapacityUnits((long) 10)
                                .withWriteCapacityUnits((long) 5))
                        .withProjection(new Projection().withProjectionType(ProjectionType.INCLUDE)
                                .withNonKeyAttributes("mg"));

                ArrayList<KeySchemaElement> indexKeySchema = new ArrayList<KeySchemaElement>();

                indexKeySchema.add(new KeySchemaElement()
                        .withAttributeName("to")
                        .withKeyType(KeyType.HASH));
                indexKeySchema.add(new KeySchemaElement()
                        .withAttributeName("cr")
                        .withKeyType(KeyType.RANGE));

                messagesFromIndex.setKeySchema(indexKeySchema);
                request.withGlobalSecondaryIndexes(messagesFromIndex);

            }


            request.setAttributeDefinitions(attributeDefinitions);

            System.out.println("Issuing CreateTable request for " + tableName);
            Table table = dynamoDB.createTable(request);
            System.out.println("Waiting for " + tableName
                    + " to be created...this may take a while...");
            table.waitForActive();

        } catch (Exception e) {
            System.err.println("CreateTable request failed for " + tableName);
            System.err.println(e.getMessage());
        }
    }

}

person user2924127    schedule 29.09.2015    source источник


Ответы (1)


В вашей конструкции кода для добавления GSI на основе имени таблицы

if(contacts.equals(tableName)){
   ...
   .withKeyType("S"));
   .withKeyType("N"));
   ...
}

и

if(messages.equals(tableName)){
   ...
   .withKeyType("S"));
   .withKeyType("N"));
   ...
}

API withKeyType(...) принимает тип ключа, например. Хэш | Диапазон, а не тип данных.

Правильный пример:

.withKeyType(KeyType.HASH));
person Oh Chin Boon    schedule 29.09.2015
comment
Спасибо за ответ. Я добавил типы ключей хэша и диапазона к обоим, но теперь получаю сообщение об ошибке, говорящее о том, что хеш-ключ глобального вторичного индекса не указан в определениях атрибутов. Тип неизвестен. - person user2924127; 30.09.2015
comment
Исключение говорит о том, что ему не удалось определить тип данных хэш-ключа, указанного GSI. В этом случае вам необходимо включить в свой список массива attributeDefinitions хеш-ключ GSI. - person Oh Chin Boon; 30.09.2015
comment
Пример: attributeDefinitions.add(new AttributeDefinition().withAttributeName(to).withAttributeType(S)); - person Oh Chin Boon; 30.09.2015
comment
Разве мой массив attributeDefenitions уже не добавляет ключ и тип из переданных параметров метода «создать таблицу»? - person user2924127; 30.09.2015
comment
Нет, из приведенных выше кодов я вижу, что только хэш таблицы и/или ключ Range добавляется в attributeDefinitions. Вам по-прежнему не хватает ключей Hash и/или Range GSI. То есть, fr, to, at, to в зависимости от таблицы. - person Oh Chin Boon; 30.09.2015
comment
Внутри оператора Contact if я добавил в первой строке: attributeDefinitions.add(new AttributeDefinition().withAttributeName(fr).withAttributeType(S));. Для сообщений я добавил: attributeDefinitions.add(new AttributeDefinition().withAttributeName(to).withAttributeType(S)); attributeDefinitions.add(new AttributeDefinition().withAttributeName(cr).withAttributeType(N)); attributeDefinitions.add(new AttributeDefinition().withAttributeName(mg).withAttributeType(S)); . Все равно выдает ошибку - person user2924127; 30.09.2015
comment
Для таблицы контактов нужны fr и st, для сообщения — to и cr. - person Oh Chin Boon; 30.09.2015
comment
Сообщение об ошибке исчезло, но появилось новое: «Не может быть двух атрибутов с одинаковым именем». Я обновил свой вопрос своим новым кодом - person user2924127; 30.09.2015
comment
Для таблицы сообщений cr дважды добавляется в список атрибутов: один раз для таблицы и один раз для GSI. Вы должны проверить и добавить, только если он не существует в списке. - person Oh Chin Boon; 30.09.2015
comment
Нп! Получайте удовольствие от DynamoDb Java API. - person Oh Chin Boon; 30.09.2015