简体   繁体   English

DynamoDBMapper仅在唯一时保存项目

[英]DynamoDBMapper save item only if unique

I'm trying to keep items in my table unique based on a combination of two different columns. 我试图根据两个不同列的组合将表中的项保持唯一。

I have an instanceId and imageId column (along with others) and based on a couple of posts on Stackoverflow and AWS Forums the below should work? 我有一个instanceId和imageId列(以及其他)并基于StackoverflowAWS论坛上的几个帖子,下面应该有效吗?

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
    }
}

However every time I try and save a duplicate item (same instanceId and imageId) it's successfully being saved into the database. 但是,每次我尝试保存重复项(相同的instanceId和imageId)时,它都会成功保存到数据库中。

Am I missing anything else here? 我在这里错过了什么?

EDIT RE notionquest answer EDIT RE notionquest回答

Updating to the answer below. 更新到下面的答案。

I have a job that runs once a minute polling an API. 我有一个每分钟运行一次API的工作。 The response from the API is represented as a Server POJO. API的响应表示为Server POJO。 The Server has an attribute named instanceId . Server有一个名为instanceId的属性。

I want to make sure that if a Server with that instanceId is already in the database, don't save it. 我想确保如果具有该instanceIdServer已经在数据库中,请不要保存它。

The Server object has another attribute of id which is set as the table primary key. Server对象具有另一个id属性,该属性被设置为表主键。

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...");
    }
}

This code will save the Server object over and over again with the exception never being thrown. 此代码将一次又一次地保存Server对象,但不会抛出异常。

The Server POJO 服务器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
}

If I correctly understood the question, you'd like to ensure uniqueness for a field which is not the hash key. 如果我正确理解了这个问题,那么您希望确保不是哈希键的字段的唯一性。

(I'm not sure why you do not use instanceId as the hash key for Servers table, I guess you have a reason for that). (我不确定为什么你不使用instanceId作为Servers表的哈希键,我想你有理由)。

My answer: looks like you can't do that without using an auxiliary table . 我的回答:看起来如果不使用辅助表就无法做到这一点

Here is your existing Servers table: 这是您现有的Servers表:

+----------------------------------------------+
|                 Servers                      |   
+----------------------------------------------+
| * id            the hash key                 |
| * instanceId    non-key field, must be unique|
|                                              |
| * ...                                        |
| * other fields                               |
| * ...                                        | 
+----------------------------------------------+

I would create an additional table with instanceId as the hash key: 我将创建一个使用instanceId作为哈希键的附加表:

+----------------------------------------------+
|                 Instance                     |   
+----------------------------------------------+
| * instanceId    the hash key                 |
+----------------------------------------------+

Having such a table, before saving a record into Servers, you have to ensure first that instanceId value is unique by adding a record (putItem) into Instance, providing a ConditionExpression like attribute_not_exists(instanceId) . 拥有这样一个表,在将记录保存到Servers之前,您必须首先通过向Instance添加记录(putItem)来确保instanceId值是唯一的,提供类似attribute_not_exists(instanceId)的ConditionExpression。

And only if the put operation completes without an ConditionalCheckFailedException error, you can proceed with adding the record into Servers. 只有在没有ConditionalCheckFailedException错误的情况下完成put操作,您才可以继续将记录添加到Servers中。

If you'd like to ensure uniqueness of records in Servers based on combination of two fields, instanceId and imageId, instead of just instanceId use concatenated values of these fields as a single field in your aux table: 如果您希望基于两个字段instanceId和imageId的组合来确保服务器中记录的唯一性,而不是只使用instanceId将这些字段的连接值用作aux表中的单个字段:

+----------------------------------------------+
|               Instance_Image                 |   
+----------------------------------------------+
| * instanceId_imageId   the hash key          |
+----------------------------------------------+

The below code checks whether the attribute value is NOT equal to "somevalue" and updates the item if the condition is satisfied. 下面的代码检查属性值是否不等于 “somevalue”,如果条件满足则更新项目。

Map<String, ExpectedAttributeValue> expected = new HashMap<>();     
expected.put("yourattribute", new ExpectedAttributeValue(new AttributeValue("yourvalue")).withComparisonOperator(ComparisonOperator.NE));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM