Статьи

Запрос элементов DynamoDB с помощью DynamoDBMapper

В предыдущем посте мы выдавали запросы к базе данных DynamoDB с использованием низкоуровневого Java API.

Запросы с использованием DynamoDBMapper довольно просты.

Выполнить запрос с использованием хеш-ключа так же просто, как и получить. Наилучшим кандидатом для такого запроса будет таблица «Пользователи», в которой поиск выполняется с использованием хэш-ключа электронной почты.

1
2
3
4
5
public User getUser(String email) {
 
        User user = dynamoDBMapper.load(User.class,email);
        return user;
    }

Поскольку мы используем только хеш-ключ для таблицы Users, наш результат будет ограничен одним.

Функция загрузки также может использоваться для составных ключей. Поэтому для запроса элемента таблицы логинов потребуется ключ хеша и ключ диапазона.

1
2
3
4
5
public Login getLogin(String email,Long date) {
 
        Login login =  dynamoDBMapper.load(Login.class,email,date);
        return login;
    }

Следующим шагом является выдача более сложных запросов с использованием условий. Мы выдадим запрос, который будет получать попытки входа в систему между двумя датами.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
public List<Login> queryLoginsBetween(String email, Long from, Long to) {
 
        Map<String,String> expressionAttributesNames = new HashMap<>();
        expressionAttributesNames.put("#email","email");
        expressionAttributesNames.put("#timestamp","timestamp");
 
        Map<String,AttributeValue> expressionAttributeValues = new HashMap<>();
        expressionAttributeValues.put(":emailValue",new AttributeValue().withS(email));
        expressionAttributeValues.put(":from",new AttributeValue().withN(Long.toString(from)));
        expressionAttributeValues.put(":to",new AttributeValue().withN(Long.toString(to)));
 
        DynamoDBQueryExpression<Login> queryExpression = new DynamoDBQueryExpression<Login>()
                .withKeyConditionExpression("#email = :emailValue and #timestamp BETWEEN :from AND :to ")
                .withExpressionAttributeNames(expressionAttributesNames)
                .withExpressionAttributeValues(expressionAttributeValues);
 
        return dynamoDBMapper.query(Login.class,queryExpression);
    }

Мы используем DynamoDBQueryExpression, так же, как мы использовали его в API низкого уровня.
Основное отличие состоит в том, что нам вообще не нужно обрабатывать пейджинг. DynamoDBMapper отобразит элементы DynamoDB на объекты, но также вернет коллекцию с отложенной загрузкой. Первоначально он возвращает только одну страницу результатов, а затем при необходимости выполняет сервисный вызов для следующей страницы.

Последний, но не менее важный запрос к индексам — это одно из основных действий. Это та же самая процедура для локальных или глобальных вторичных индексов.
Имейте в виду, что полученные результаты зависят от типа проекции, который мы указали при создании таблицы. В нашем случае тип проекции — для всех полей.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public Supervisor getSupervisor(String company,String factory) {
 
        Map<String,String> expressionAttributesNames = new HashMap<>();
        expressionAttributesNames.put("#company","company");
        expressionAttributesNames.put("#factory","factory");
 
        Map<String,AttributeValue> expressionAttributeValues = new HashMap<>();
        expressionAttributeValues.put(":company",new AttributeValue().withS(company));
        expressionAttributeValues.put(":factory",new AttributeValue().withS(factory));
 
        DynamoDBQueryExpression<Supervisor> dynamoDBQueryExpression = new DynamoDBQueryExpression<Supervisor>()
                .withIndexName("FactoryIndex")
                .withKeyConditionExpression("#company = :company and #factory = :factory ")
                .withExpressionAttributeNames(expressionAttributesNames)
                .withExpressionAttributeValues(expressionAttributeValues)
                .withConsistentRead(false);
 
        List<Supervisor> supervisor = dynamoDBMapper.query(Supervisor.class,dynamoDBQueryExpression);
 
        if(supervisor.size()>0) {
            return supervisor.get(0);
        } else {
            return null;
        }
    }

Обратите особое внимание на то, что для согласованного чтения установлено значение false. DynamoDBQueryExpression использует по умолчанию согласованные чтения. При использовании глобального вторичного индекса вы не можете выполнить согласованное чтение.

Вы можете найти полный исходный код с юнит-тестами на github .