我试图根据两个不同列的组合将表中的项保持唯一.
我有一个instanceId和imageId列(以及其他)并基于Stackoverflow和AWS Forums上的几个帖子,下面应该有效吗?
public void saveUnique(Server server) { DynamoDBSaveExpression saveExpression = new DynamoDBSaveExpression(); Map<String,ExpectedAttributeValue> expectedAttributes = ImmutableMap.<String,ExpectedAttributeValue>builder() .put("instanceId",new ExpectedAttributeValue(false)) .put("imageId",new ExpectedAttributeValue(false)) .build(); saveExpression.setExpected(expectedAttributes); saveExpression.setConditionalOperator(ConditionalOperator.AND); try { mapper.save(server,saveExpression); } catch (ConditionalCheckFailedException e) { //Handle conditional check } }
但是,每次我尝试保存重复项(相同的instanceId和imageId)时,它都会成功保存到数据库中.
我在这里错过了什么?
编辑R.E notionquest答案
更新到下面的答案.
我有一个每分钟运行一次API的工作. API的响应表示为服务器POJO.服务器具有名为instanceId的属性.
我想确保如果具有该instanceId的服务器已经在数据库中,请不要保存它.
public void saveUnique(Server server) { DynamoDBSaveExpression saveExpression = new DynamoDBSaveExpression(); Map<String,ExpectedAttributeValue> expected = new HashMap<>(); expected.put("instanceId",new ExpectedAttributeValue(new AttributeValue(server.getInstanceId())).withComparisonOperator(ComparisonOperator.NE)); saveExpression.setExpected(expected); try { mapper.save(server,saveExpression); } catch (ConditionalCheckFailedException e) { LOGGER.info("Skipped saving as not unique..."); } }
此代码将一次又一次地保存Server对象,但不会抛出异常.
服务器POJO
@DynamoDBTable(tableName = "Servers") public class Server { @Id private String id = UUID.randomUUID().toString(); @DynamoDBTypeConvertedJson private Task task; @DynamoDBAttribute(attributeName = "instanceId") private String instanceId; public Server() { } @DynamoDBHashKey public String getId() { return id; } // other standard getters and setters }
解决方法
如果我正确理解了这个问题,那么您希望确保不是哈希键的字段的唯一性.
(我不确定为什么你不使用instanceId作为Servers表的哈希键,我想你有理由这样做).
我的回答:看起来如果不使用辅助表就无法做到这一点.
这是您现有的Servers表:
+----------------------------------------------+ | Servers | +----------------------------------------------+ | * id the hash key | | * instanceId non-key field,must be unique| | | | * ... | | * other fields | | * ... | +----------------------------------------------+
我将创建一个使用instanceId作为哈希键的附加表:
+----------------------------------------------+ | Instance | +----------------------------------------------+ | * instanceId the hash key | +----------------------------------------------+
拥有这样的表,在将记录保存到服务器之前,您必须这样做
首先通过向Instance添加记录(putItem)来确保instanceId值是唯一的,提供一个ConditionExpression,如attribute_not_exists(instanceId).
并且只有在没有ConditionalCheckFailedException错误的情况下完成put操作时,您才可以继续将记录添加到Servers中.
如果您想基于两个字段instanceId和imageId的组合来确保服务器中记录的唯一性,
而不是只是instanceId使用这些字段的连接值作为aux表中的单个字段:
+----------------------------------------------+ | Instance_Image | +----------------------------------------------+ | * instanceId_imageId the hash key | +----------------------------------------------+