使用 DynamoDBSaveExpression 检查其他密钥是否存在

Using DynamoDBSaveExpression to Check Existence of Other Key

作为一个简单的例子,我有一个 class 看起来像这样:

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

此 class 存储在 DynamoDB table 中。将新条目添加到 table 时,我想确保父项已经存在(如果设置了父项)。

这可以使用 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);

编辑

有一个RESTfulAPI定义了一个POST来创建一个资源,资源作为一个条目存储在DynamoDBtable中。

该资源允许使用父标识符指定的层次结构。

如果找不到父资源,则 returned:

会返回 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' 可能 return 父级,但另一个 thread/process 可能会在 'e'.

之前删除它

我希望条件表达式在这里有所帮助。 transaction library 是完成此任务的唯一方法吗?或者,是否应该对数据进行不同的建模?

下面的答案基本上已经过时了,但我将它留给后代。 DynamoDB now supports transactions 允许您为相同或另一个 table.

中的不同键值提供条件表达式

不,ConditionExpression 不能查看当前项目以外的任何项目 saved/updated/deleted。

更新

如果可能的话,你能不能把你的数据设计成不能删除的东西? (也许您可以将其标记为过时。)这完全消除了问题,因为一旦某物存在,它将永远存在。

如果那不可能,您可能想看看 DynamoDBLockClient。它提供了由 DynamoDB 支持的通用分布式锁定 API。

你的新伪代码是

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

此外,在删除父标识符的任何操作中,您应该在删除父标识符之前获取该父标识符的锁。如果这样做,您可以确保父对象不会在创建子对象的过程中被删除。