thebighoncho
thebighoncho

Reputation: 405

DynamoDB Expression - multiple ExpectedAttributeValues comparisons

I am attempting to use DynamoDB's DynamoDBSaveExpression using the java sdk.

I am in a position where I am trying to emulate the following two scenarios:

1) if the item exists in the table, enforce the save expression restrictions DATE1, DATE2, and DATE3 (see code below).

2) if the item does not exist in the table, attempt to insert it.

Here is my code so far:

        ExpectedAttributeValue date1 = new ExpectedAttributeValue()
                .withComparisonOperator(ComparisonOperator.LE)
                .withValue(new AttributeValue().withN(Long.toString(tr.date1().getTime())));

        ExpectedAttributeValue date2 = new ExpectedAttributeValue()
                .withComparisonOperator(ComparisonOperator.LE)
                .withValue(new AttributeValue().withN(Long.toString(tr.date2().getTime())));

        ExpectedAttributeValue date3 = new ExpectedAttributeValue()
                .withComparisonOperator(ComparisonOperator.LE)
                .withValue(new AttributeValue().withN(Long.toString(tr.date3().getTime())));



        DynamoDBSaveExpression saveExpression = new DynamoDBSaveExpression();
        Map<String, ExpectedAttributeValue> expectedAtributes =
                ImmutableMap.<String, ExpectedAttributeValue>builder()
                        .put("date1", date1)
                        .put("date2", date2)
                        .put("date3", date3)
                        .build();

        saveExpression.setExpected(expectedAtributes);
        saveExpression.setConditionalOperator(ConditionalOperator.AND);

I am unsure how to use the Save Expressions to capture both scenarios. Please note I am aware I can dynamically pass in a separate Save Expression but doing so would involve significant refactoring which my client does not want.

Upvotes: 1

Views: 2434

Answers (1)

Alexander Patrikalakis
Alexander Patrikalakis

Reputation: 5195

Try an UpdateItem call that conditions on the item NOT existing and catch a ConditionalCheckFailedException. In the catch block, you know that the item existed so you can do an UpdateItem call that conditions on the item existing and meeting the conditions above. You are not able to set attribute_exists conditions with the Mapper, so you will need to use the low-level API or the Document SDK to take advantage of this functionality.

try {
    table.updateItem(new UpdateItemSpec().withPrimaryKey(...)
        .withConditionExpression("attribute_not_exists(my_hash_key)")
        //one for each attribute of the item you are creating
        .withAttributeUpdate(new AttributeUpdate("attribute_name")
                                            .put("attribute_value")) 
    );
} catch(ConditionalCheckFailedException e) {
    table.updateItem(new UpdateItemSpec().withPrimaryKey(...)
        .withConditionExpression("attribute_exists(my_hash_key)")
        .withUpdateExpression("SET attributeToChange = :val")
        .withExpressionAttributeValues(ImmutableMap.of(":val", "asdf")) 
    );
}

Upvotes: 1

Related Questions