How to check if a non-classical attribute exists in dynamodb using ConditionExpression?

I want to insert users into the table only if userId, email and username do not exist (you want them to be unique).
userId - primary key (Hash key, data type - Number).
username and email address are non-key attributes (both lines).

Here is how I tried:

response = userTable.put_item( Item={ 'userId': userIdNext, 'accType': 0, 'username': usernameInput, 'pwd': hashedPwd, 'email': emailInput }, ConditionExpression = "(attribute_not_exists(userIdNext)) AND (NOT (contains (email, :v_email))) AND (NOT (contains(username, :v_username)))", ExpressionAttributeValues={ ":v_email": emailInput, ":v_username": usernameInput } ) 

I tried here to execute aws documentation for boolean operators and condition expressions: AWS conditional expressions

But it inserts each time into the table, even if the username or email address already exists in db.
(I give the new userIdNext as the primary key and cannot be a duplicate)

I am using Python boto3 implementation

+5
source share
2 answers

dynamodb can format uniqueness only for hash-range table keys (and not for global secondary index keys)

in your case there are 2 options:

1) force it at the application level - request records and find a duplicate

2) add another dynamodb table with hash / range values ​​(which can ensure uniformity), you can query this table before placing an element in the main table

3) use application locks (memcache ..)

4) Do not use dynamodb (maybe it does not meet your requirements)

referring to your answers here:

DynamoDB avoids duplication of non-key attributes

DynamoDB reconciliation for global secondary index

+4
source

Ok, I found an error in my application.

I am trying to make a put conditional element in DynamoDB, but I am passing another primary key that exists in DynamoDB, at that moment a new object will be created and the conditional expression will be ignored.

 # id primary key id = 123 # email is only index email = " email@email.com " item = { "id": id, "email": email "info": { "gender": "male", "country": "Portugal" } } response = self._table.put_item(Item=item, ConditionExpression="email <> :v_email", ExpressionAttributeValues={":v_email": email}) 

If you want conditional expressions to work fine on DynamoDB put_item, you must send the same primary key that exists in the database.

kishorer747, can you put a sample of your code that will do this? β€œI have Global secondary indexes to check for a username or email already, but not atomic. Therefore, if 2 users request at the same time and access email1, they are both inserted into the users table. And also if there is no check to check whether there is already a name / username, we have duplicate entries for email / username "

+1
source

Source: https://habr.com/ru/post/1243639/


All Articles