- Newest
- Most votes
- Most comments
Hi Dawn - I was able to get the conditional PutItem you're looking for to work with the basic Java v1 SDK as follows....
private static PutItemRequest createPutItemRequest() {
PutItemRequest putItemRequest = new PutItemRequest();
putItemRequest.setTableName("condexpr");
putItemRequest.setItem(getItem());
String conditionExpression = "attribute_not_exists(#3a350) Or NOT (#3a351 = :3a351)";
putItemRequest.setConditionExpression(conditionExpression);
putItemRequest.setExpressionAttributeNames(getExpressionAttributeNames());
putItemRequest.setExpressionAttributeValues(getExpressionAttributeValues());
return putItemRequest;
}
private static Map<String, AttributeValue> getItem() {
Map<String, AttributeValue> item = new HashMap<String, AttributeValue>();
item.put("id", new AttributeValue("user1"));
item.put("score", new AttributeValue().withN("110"));
item.put("status", new AttributeValue("REDEEMED"));
return item;
}
private static Map<String, String> getExpressionAttributeNames() {
Map<String, String> expressionAttributeNames = new HashMap<String, String>();
expressionAttributeNames.put("#3a350", "id");
expressionAttributeNames.put("#3a351", "status");
return expressionAttributeNames;
}
private static Map<String, AttributeValue> getExpressionAttributeValues() {
Map<String, AttributeValue> expressionAttributeValues = new HashMap<String, AttributeValue>();
expressionAttributeValues.put(":3a351", new AttributeValue("PENDING"));
return expressionAttributeValues;
}
Maybe you could try something like the following?
Expression conditionExpression
= Expression.builder()
.expression("attribute_not_exists(#myId) OR NOT (#currentStatus = :pendingStatus)")
.putExpressionName("#myId", "userId")
.putExpressionName("#currentStatus", "status")
.putExpressionValue(":pendingStatus", AttributeValue.builder().s("PENDING").build())
.build();
Ah, I think I misunderstood your design. In your original message you mentioned that userId is the partition (hash) key for your table, but did not mention a sort key. Now starting to believe that you might be using one of the attributes (perhaps status) as the sort key? I think that if you take an approach where you have a simple primary key (just the partition key attribute userId - no sort key), my proposed solution will work for you. It does not maintain a complete history of the status stages that a given user might go through - instead, updating an existing item in place for that userId if their status changes in a way that meets your set of conditions. Does that make sense?
Using transactions per the blog you linked may be an option, but it's heavy, and I think not justified.
Hi, apologize for not being clear in my example, I simplified the issue in my example in an attempt to explain what I want to achieve, but yes, actually I am using a hashkey and a sortKey. I think in this case, it cannot be achieved unless using transactions, but still really appreciate the answers!
Interesting - it worked in my testing. Any chance you didn't match the case on "PENDING" ? The expression check is case sensitive.
Actually I get to know that DynamoDB does not evaluate the entire database when you put a condition on an attribute, it only evaluates the item you are operating on. So the condition is happening on completely different items. Alternative: https://aws.amazon.com/blogs/database/simulating-amazon-dynamodb-unique-constraints-using-transactions/
Relevant content
- Accepted Answerasked 2 years ago
- Accepted Answerasked 5 months ago
- asked 9 months ago
- AWS OFFICIALUpdated 2 years ago
- AWS OFFICIALUpdated 2 years ago
- AWS OFFICIALUpdated 2 years ago
- AWS OFFICIALUpdated 8 months ago
Hi, thanks for replying! However I tested it the proposed solution myself, it did not work for below case: