Я пытаюсь проверить, существует ли элемент в моей таблице Dynamodb, используя приведенный ниже код: Я хочу иметь возможность запускать что-то, как только смогу получить этот элемент. Ключ раздела - envName , а ключ сортировки - имя_конфигурации .

package com.dev.newlibs;

//all relevant imports added here

public class updatenewCMDB {
    
    public static void main(String[] args)throws Exception {
        String tableName = "env_dashboard";
        String configurationName = "component";
        String configurationNameValue = "ec2";
        String envName = "env_Name";
        String envNameValue = "dev";
        String status = "status"; 
        String statusValue = "COMPLETE";

        DynamoDbClient client = DynamoDbClient.builder()
                .region(Region.EU_WEST_1)
                .build();
            
            client.close();

            updateEnvDashboard(client, tableName, configurationName, configurationNameValue, envName, envNameValue, status, statusValue,);
    }

    public static void updateEnvDashboard(DynamoDbClient client,
                                         String tableName, 
                                         String configurationName,
                                         String configurationNameValue,
                                         String envName,
                                         String envNameValue,
                                         String status, 
                                         String statusValue,) throws Exception {

        
        //Get item to see if it exists
        HashMap<String,AttributeValue> itemToGet = new HashMap<String,AttributeValue>();
        
        itemToGet.put(configurationName, AttributeValue.builder().s(configurationNameValue).build());
        itemToGet.put(status, AttributeValue.builder().s(statusValue).build());
        itemToGet.put(envName, AttributeValue.builder().s(envNameValue).build());


        GetItemRequest request = GetItemRequest.builder()
                .key(itemToGet)
                .tableName(tableName)
                .build();
        
        //run a get request and see what is returned. do something depending on what is returned
        
        try {
            Map<String,AttributeValue> returnedItem = client.getItem(request).item();
            if (returnedItem != null) {
                Set<String> keys = returnedItem.keySet();
                System.out.println("Amazon DynamoDB table attributes: \n");

                for (String key1 : keys) {
                    System.out.format("%s: %s\n", key1, returnedItem.get(key1).toString());
                }
            } else {
                System.out.format("No item found with the key %s!\n");
            }
            
        } catch (DynamoDbException e){
            e.printStackTrace();
            System.exit(1);
        }
        
    }
}

При запуске я получаю сообщение об ошибке:

software.amazon.awssdk.services.dynamodb.model.DynamoDbException: The provided key element does not match the schema

Что мне здесь не хватает? Я попытался последовать примеру getItem из официального репозитория aws

0
TheSuperDoughnut 10 Сен 2021 в 19:22

2 ответа

Лучший ответ

При вызове GetItem.

Вы включили неключевые атрибуты (status). Когда вы предоставляете неключевые атрибуты, ваш запрос GetItem завершится ошибкой с ValidationException, включая это сообщение об ошибке:

The provided key element does not match the schema

Измените свой GetItemRequest , чтобы включить только ключевые атрибуты (envName и configurationName) и убедиться, что они имеют правильные типы данных (обе строки).

Чтобы проверить, что происходит, часто бывает полезно подтвердить свои предположения с помощью файла awscli. Вот пример того, как выполнить тот же вызов GetItem с помощью awscli:

aws dynamodb get-item \
    --table-name mytable \
    --key '{"envName":{"S":"env1"}, "configurationName":{"S":"config1"}}'

Некоторые важные базовые знания о DynamoDB: вы не можете получить элемент, не указав его полный ключ, который в вашем случае равен envName плюс configurationName. Если вместо конкретного отдельного элемента вы действительно хотите, чтобы все элементы имели заданный envName, вы можете выполнить запрос (вместо GetItem) с помощью только ключа раздела envName. Вы не можете получить / запросить ключ сортировки, поэтому вы не сможете запросить все элементы с данным configurationName ... если вы не создадите глобальный вторичный индекс (GSI) для этого атрибута ключа сортировки, а затем не укажете GSI имя при запросе.

2
jarmod 10 Сен 2021 в 19:09

Я предлагаю вам взглянуть на использование расширенного клиента Amazon DynamoDB для получения элемента. Используя расширенный клиент, вы можете сопоставить клиентские классы с таблицами DynamoDB. Для получения дополнительной информации см. Использование расширенный клиент DynamoDB в составе AWS SDK для Java 2.x.

Например, предположим, что вы хотите получить данные о клиентах из таблицы «Клиент».

enter image description here

Вот класс Java Клиент .

package com.example.dynamodb;

import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable;
import software.amazon.awssdk.enhanced.dynamodb.TableSchema;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey;
import software.amazon.awssdk.enhanced.dynamodb.model.BatchWriteItemEnhancedRequest;
import software.amazon.awssdk.enhanced.dynamodb.model.WriteBatch;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;

/**
 * This class is used by the Enhanced Client examples.
 */

 @DynamoDbBean
 public class Customer {

        private String id;
        private String name;
        private String email;
        private Instant regDate;

        @DynamoDbPartitionKey
        public String getId() {
            return this.id;
        };

        public void setId(String id) {

            this.id = id;
        }

        public String getCustName() {
            return this.name;
        }

        public void setCustName(String name) {
            this.name = name;
        }

        public String getEmail() {
            return this.email;
        }

        public void setEmail(String email) {
            this.email = email;
        }

        public Instant getRegistrationDate() {
            return regDate;
        }
        public void setRegistrationDate(Instant registrationDate) {

            this.regDate = registrationDate;
        }
    }

Вы можете получить запись клиента, используя этот код:

package com.example.dynamodb;

// snippet-start:[dynamodb.java2.mapping.getitem.import]
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable;
import software.amazon.awssdk.enhanced.dynamodb.Key;
import software.amazon.awssdk.enhanced.dynamodb.TableSchema;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import java.time.Instant;
// snippet-end:[dynamodb.java2.mapping.getitem.import]

/*
 * Prior to running this code example, create an Amazon DynamoDB table named Customer with these columns:
 *   - id - the id of the record that is the key
 *   - custName - the customer name
 *   - email - the email value
 *   - registrationDate - an instant value when the item was added to the table
 *
 * Also, ensure that you have setup your development environment, including your credentials.
 *
 * For information, see this documentation topic:
 *
 * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
 */

public class EnhancedGetItem {

    public static void main(String[] args) {

        Region region = Region.US_EAST_1;
        DynamoDbClient ddb = DynamoDbClient.builder()
                .region(region)
                .build();

        DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()
                .dynamoDbClient(ddb)
                .build();

        String result = getItem(enhancedClient);
        System.out.println(result);
        ddb.close();
    }

    // snippet-start:[dynamodb.java2.mapping.getitem.main]
    public static String getItem(DynamoDbEnhancedClient enhancedClient) {
        try {
            //Create a DynamoDbTable object
            DynamoDbTable<Customer> mappedTable = enhancedClient.table("Customer", TableSchema.fromBean(Customer.class));

            //Create a KEY object
            Key key = Key.builder()
                    .partitionValue("id146")
                    .build();

            // Get the item by using the key
            Customer result = mappedTable.getItem(r->r.key(key));
            return "The email value is "+result.getEmail();

        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }

        return "";
    }
    // snippet-end:[dynamodb.java2.mapping.getitem.main]
}

Как вы можете видеть в этом представлении отладки, этот код извлекает запись клиента.

enter image description here

Также - в примере кода в вашем потоке вы закрываете клиент перед вызовом метода:

DynamoDbClient client = DynamoDbClient.builder()
                .region(Region.EU_WEST_1)
                .build();
            
            client.close(); // bug here

            updateEnvDashboard(client, tableName, configurationName, configurationNameValue, envName, envNameValue, status, statusValue,);
1
smac2020 10 Сен 2021 в 19:07