I just tried it with an attributes_not_exists
condition and it seems to work as expected:
$ aws create-table --table-name example1 \
--attribute-definitions AttributeName=pk,AttributeType=S \
--key-schema AttributeName=pk,KeyType=HASH --billing-mode PAY_PER_REQUEST
...
$ aws dynamodb put-item --table-name example1 \
--item '{"pk": {"S": "abc"}, "city": {"S": "NYC"}}'
$ aws scan --table-name example1
{
"Items": [
{
"city": {
"S": "NYC"
},
"pk": {
"S": "abc"
}
}
],
"Count": 1,
"ScannedCount": 1,
"ConsumedCapacity": null
}
$ aws dynamodb put-item --table-name example1 \
--item '{"pk": {"S": "abc"}, "city": {"S": "SF"}}' \
--condition-expression "attribute_not_exists(pk)"
An error occurred (ConditionalCheckFailedException) ...
$
Why did your request fail?
Based on the request you posted, I believe the culprit is your condition expression.
Instead of "attribute_not_exists(:username)"
it should be attribute_not_exists(username)
. the :
prefix denotes a value place holder whereas the attribute_not_exists
function does not need a value, it needs an attribute name. Once you make the change you will also need to remove the ExpressionAttributeValues
field because the value placeholder it defines (namely: :username
) is no longer used anywhere in the request.
So, to summarize, this request should work for you:
Key: {
username: event.pathParameters.username
},
Item: {
userId: event.requestContext.identity.cognitoIdentityId
},
ConditionExpression: "attribute_not_exists(username)"
One last (super minor) comment: the request you posted looks like an update request. I believe that for your use case you can use put which needs a somewhat simpler request. Specifically, in put
you just specify the entire item, you do not need to specify the key separately from the other attributes. Note that just like update
, put
also supports a ConditionExpression
which is the critical piece in the solution.