Использование DynamoDBSaveExpression для проверки наличия другого ключа

В качестве простого примера у меня есть класс, который выглядит так:

public class DbData {
    @DynamoDBAutoGeneratedKey
    @DynamoDBHashKey(attributeName = "id")
    private UUID id;
    private UUID parent;
    // other fields ...
}

Этот класс хранится в таблице DynamoDB. Когда в таблицу добавляется новая запись, я хочу убедиться, что родительский элемент уже существует (если родительский элемент установлен).

Можно ли это сделать с помощью DynamoDBSaveExpression?

Например, я могу убедиться, что текущий id не существует:

new DynamoDBSaveExpression()
    .withExpectedEntry("id", new ExpectedAttributeValue().withExists(false));

Я думал, что это может сработать, но это не так:

    ExpectedAttributeValue expectedAttributeValue = new ExpectedAttributeValue(new AttributeValue(parent.toString()));
    dynamoDBSaveExpression = new DynamoDBSaveExpression()
            .withExpectedEntry("id", new ExpectedAttributeValue().withExists(false));
            .withExpectedEntry("id", expectedAttributeValue.withExists(true))
            .withConditionalOperator(ConditionalOperator.AND);

Редактировать

Существует RESTful API, который определяет POST для создания ресурса, и ресурс сохраняется как запись в таблице DynamoDB.

Ресурс допускает иерархию, которая указывается с помощью родительского идентификатора.

Если родительский ресурс не найден, возвращается 404:

a. if parent identifier is set
b.     get parent resource from DynamoDB
c.     if parent not found
d.         return 404
e. persist resource in DynamoDB

Псевдокод не атомарен. 'b' может вернуть родителя, но другой поток / процесс может удалить его до 'e'.

Я надеялся, что здесь поможет выражение условия. библиотека транзакций - единственный способ добиться этого? Или данные следует моделировать по-другому?

Если вы можете предоставить дополнительную информацию о своем варианте использования, кто-то может предложить альтернативное решение.

Matthew Pope 24.11.2018 06:28

Я обновил вопрос с помощью варианта использования, спасибо за предложение.

mustbealennox 26.11.2018 05:39

Сделки DynamoDB были объявлены вчера на конференции re: Invent. Они могут стать для вас решением. Я пока не знаю, как именно они работают, но рекомендую вам ознакомиться с документацией на docs.aws.amazon.com/amazondynamodb/latest/developerguide/….

Matthew Pope 30.11.2018 08:37
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
3
866
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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


Нет, ConditionExpression не может просматривать какие-либо элементы, кроме текущего, который сохраняется / обновляется / удаляется.

Обновлять

Если возможно, можете ли вы создать свои данные таким образом, чтобы их нельзя было удалить? (Возможно, вместо этого вы можете пометить его как устаревший.) Это полностью устраняет проблему, потому что если что-то существует, оно будет существовать всегда.

Если это невозможно, вы можете посмотреть DynamoDBLockClient. Он предоставляет универсальный API распределенной блокировки, поддерживаемый DynamoDB.

Ваш новый псевдокод будет

a. if parent identifier is set
b.     Acquire lock for parent identifier
c.     get parent resource from DynamoDB
d.     if parent not found
e.         Release lock
f.         return 404
g. persist resource in DynamoDB
h. Release lock

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

Другие вопросы по теме