If I have a table with a hash key of userId and a range key of productId how do I put an item into that table only if it doesn't already exist using boto3's dynamodb bindings?
The normal call to put_item looks like this
table.put_item(Item={'userId': 1, 'productId': 2})
My call with a ConditionExpression looks like this:
table.put_item( Item={'userId': 1, 'productId': 2}, ConditionExpression='userId <> :uid AND productId <> :pid', ExpressionAttributeValues={':uid': 1, ':pid': 3} )
But this raises a ConditionalCheckFailedException every time. Whether an item exists with the same productId or not.
The documentation for this unfortunately isn't super clear. I needed to accomplish something similar, and here's what worked for me, using boto3:
try: table.put_item( Item={ 'foo':1, 'bar':2, }, ConditionExpression='attribute_not_exists(foo) AND attribute_not_exists(bar)' ) except botocore.exceptions.ClientError as e: # Ignore the ConditionalCheckFailedException, bubble up # other exceptions. if e.response['Error']['Code'] != 'ConditionalCheckFailedException': raise
Similar to the other answer, the key is in the attribute_not_exists function, but it was unclear to me initially how to get that to work. After some experimentation, I was able to get it going with the above.
You dont need the sortkey( or range key) just the partition key or hash key is enough.
try: table.put_item( Item={ 'foo':1, 'bar':2, }, ConditionExpression='attribute_not_exists(foo)' ) except botocore.exceptions.ClientError as e: # Ignore the ConditionalCheckFailedException, bubble up # other exceptions. if e.response['Error']['Code'] != 'ConditionalCheckFailedException': raise
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With