Amazon dynamodb 如何在非主键属性上使用DynamoDB条件putItem来保证唯一性?

Amazon dynamodb 如何在非主键属性上使用DynamoDB条件putItem来保证唯一性?,amazon-dynamodb,Amazon Dynamodb,我正在为我们的一个产品实现一个名为default naming的功能,我想看看conditional putItem如何帮助我实现我们的业务逻辑需求 问题是: 我们有一个遗留的dynamoDB表,它存储一些实体信息。模式为:entityId、名称、制造商 entityId是主键,它实际上是一个UUID,名称和制造商只是属性 现在,当我们向表中插入一个新条目时,我们的特性需要生成一个默认名称。每个制造商的默认名称必须是唯一的,我们希望使用序列号来表示它 在表中,我们有两个现有项目 123, lu

我正在为我们的一个产品实现一个名为default naming的功能,我想看看conditional putItem如何帮助我实现我们的业务逻辑需求

问题是:

我们有一个遗留的dynamoDB表,它存储一些实体信息。模式为:entityId、名称、制造商

entityId是主键,它实际上是一个UUID,名称和制造商只是属性

现在,当我们向表中插入一个新条目时,我们的特性需要生成一个默认名称。每个制造商的默认名称必须是唯一的,我们希望使用序列号来表示它

在表中,我们有两个现有项目

123,  lucy, apple
3672, tom, apple
现在,如果我想在表中插入制造商apple的另一个条目,我需要生成“third”作为name属性

5678, third, apple
这似乎很简单,我只需读取apple的所有实体并获得一个计数,然后使用计数+1作为name属性的默认值

然而,我们的系统是分布式的,可能会出现多个请求,并且可能会发生竞争情况。如果我不做任何预防。两个请求可以在表中插入两个条目

5678, third, apple
9374, third, apple
相反,我们希望他们是真实的

5678, third, apple
9374, forth, apple

要解决这个问题,我想的是使用带有条件表达式的putItem。对于上面的示例,首先进行读取,得到计数2,然后如果两个并发请求尝试插入

将“5678,第三个,苹果”和“9374,第三个,苹果”放入表中,然后其中一个应该出现异常,我们可以再次增加计数并重试

安全守则是

try {
    Expected expect = new Expected("name").notExist();
    PutItemSpec putItemSpec = new PutItemSpec().withItem(item).withExpected(expected);
   entityTable.putItem(putItemSpec);
} catch (ConditionalExpression ex) {
   .. increment count and do retry
}

但是我发现这不起作用,没有抛出异常。我是否误解了有条件看跌期权?如何实现我的目标?

条件表达式不能用于此目的。ConditionExpression在DynamoDB中对于来自RDBMS世界的人来说可能有点误导。不能将其视为RDBMS表约束检查

解释

ConditionExpression在PutItemUpdateItemDeleteItem操作中指定。这些操作对表定义的唯一键进行操作,该键可以是散列键,也可以是散列+排序键

因此,当运行这些操作时,unique键标识表中的唯一项。这些情况可能如下

  • PutItem-已存在具有相同唯一键的另一项
  • UpdateItem-找到要更新的项
  • DeleteItem-找到要删除的项目
ConditionExpression只对所选项目进行操作,以执行条件检查。因此,它不能用于检查同一表中其他项的条件,也不能用于检查其他非键属性之间的唯一性

参考:

建议


为了恰当地处理这种情况,应该检查表的关键设计。请参见

以这种方式使用ConditionalPression无法帮助您确保非关键字段的唯一性。请看我的答案。它似乎完全适合您的情况。@xtx好的,谢谢。你的帖子可以解决我的问题。但我有一个关于条件put的问题,条件put是否只对散列键的属性有效?
try {
    Expected expect = new Expected("name").notExist();
    PutItemSpec putItemSpec = new PutItemSpec().withItem(item).withExpected(expected);
   entityTable.putItem(putItemSpec);
} catch (ConditionalExpression ex) {
   .. increment count and do retry
}