By default DynamoDB will make a new entry if an object with the specified index doesn't exist. Is there a way to stop this from occurring? I could just query the table for the key before updating, but it would be nice to do it all in one request.
-
You would do this with a conditional expression. The documentation is here http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.SpecifyingConditions.html – Mark B Jul 23 '16 at 19:02
-
This was answered in https://stackoverflow.com/questions/41873769/how-to-prevent-creating-a-new-item-in-updateitem-if-the-item-does-not-exist/41874889#41874889 – Adam Aug 14 '19 at 14:39
4 Answers
Use conditional expression id = :id
where id
is the attribute name (or primary key name in your case) and :id
is the value (key of the item you want to update).
Conditional expression is always evaluated before any writing. If that expression doesn't evaluate to true
(and it doesn't if that key doesn't exist or is different), it doesn't update or put a new item.

- 6,687
- 7
- 35
- 67
The key point is that ConditionExpression
is reviewed on different data sets depending on the operation you're performing PutItem
or UpdateItem.
PutItem.
When setting ConditionExpression
DynamoDB will check your condition on any of the Key rows - many rows if using range attribute on the table or just 1 if only using a hash for your table -.
Remember DynamoDB PutItem operation has to check if the Key you pass already exists, so no extra cost for checking your condition here.
For example, if you have a CUSTOMER_CONTACTS table with customer_id/contact_email key definition and don't want to create duplicates, you can set ConditionExpression = "#contact_email <> :email"
. In that case PutItem operation will fail with ConditionalCheckFailedException if the same email (range attribute) is used for the specified hash value.
But don't expect to check for item attributes far from your hash rows. No sense for DynamoDB to scan all the table just for checking your condition.
Update Item.
If you try the same condition as for previous example ConditionExpression = "#contact_email <> :email"
the operation is always overriding without triggering an exception. Why? Because UpdateItem is just looking at 1 item, the one specified by your Key.
When using UpdateItem the ConditionExpression will look at only 1 row, the one specified by the Key values you have to set. No way to check your condition on any other table row.

- 523
- 9
- 10
To give a more concrete example of Solo's answer, the following would be a CLI command to update an item that uses condition expressions to make sure the row exists before performing an update.
This prevents DynamoDB from creating a new record if the ID used doesn't exist.
aws dynamodb update-item \
--table-name ProductCatalog \
--key '{"Id": {"N": "456"}}' \
--update-expression "SET Price = :price" \
--condition-expression "id = :id" \
--expression-attribute-values file://values.json
With a values.json containing the following:
{
":price": { "N": "75"},
":id": {"N": "456"}
}

- 7,398
- 2
- 34
- 53
You probably looking for attribute_not_exists
check in Condition Expressions
.
When this conditional expression is used with the PutItem, DynamoDB first looks for an item whose primary key matches that of the item to be written. Only if the search returns nothing is there no partition key present in the result. Otherwise, the attribute_not_exists function above fails and the write will be prevented

- 33,215
- 43
- 135
- 193
-
1It looked from the documentation that `attribute_not_exists` checks whether or not a row has a certain attribute, not if a row with that key exists. Is this the case? And wouldn't I want to use `attribute_exists` since I want it to update the row if one is already there and do nothing if none are found? – Jul 24 '16 at 01:07
-
7You're right Bananable, I tried using 'attribute_exists' and it definitely doesn't prevent inserting an item, as it only checks if a row has a certain attribute. Have you found any solution for this? – George Aug 18 '16 at 12:21