Reputation: 765
I've got a table in dynamodb that only has a partition key, and I want to put an item in the db only if there isn't another item with the same partition key in the db.
I've tried using ConditionExpression attribute_not_exists to no avail.
The issue is that a certain item may not already exist in the db, so attribute_not_exists fails with an Invalid ConditionExpression: Operator or function requires a document path; operator or function: attribute_not_exists
Edit: Can you please post the full condition expression you used + the name of the table's partition key? –
Key: {
username: event.pathParameters.username
},
ExpressionAttributeValues: {
":username": event.pathParameters.username
},
Item: {
userId: event.requestContext.identity.cognitoIdentityId
},
ConditionExpression: "attribute_not_exists(:username)"
Upvotes: 8
Views: 10205
Reputation: 30723
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) ...
$
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.
Upvotes: 5