2016-02-23 3 views
5

Я хочу вставить в таблицу users только в том случае, если userId, email и username не существуют (хотите, чтобы они были уникальными).
userId является первичным ключом (клавиша Hash, тип данных - номер).
имя пользователя и адрес электронной почты являются не-ключевыми атрибутами (обе строки).Как проверить, существует ли неклассический атрибут в dynamodb с помощью ConditionExpression?

Вот как я попробовал:

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 
} 
) 

Я пытался следовать AWS документации для логических операторов и выражение условия здесь: AWS Conditional Expressions

Но вставляет каждый раз в таблицу, даже если имя пользователя или электронная почта уже существует в db.
(я даю новый userIdNext как он является первичным ключом и не может быть дубликатом)

Я использую Python реализация boto3

ответ

4

dynamodb может заставить уникальность только для ключей таблицы хеш-диапазона (а не для глобальные ключи вторичных индексов)

в вашем случае есть 2 варианта:

1) принуждает его на уровне приложения - запрос для записей, и найти, если дублировать

2) добавить еще одну таблицу dynamodb со значениями хэш/диапазона (который может обеспечивать uniqeness), вы можете запросить эту таблицу, прежде чем положить товар в основной таблице

3) использовать блокировки приложений (Memcache ..)

4) не использовать dynamodb (может быть, его не отвечать на ваши требования)

направить вас к ответам здесь:

DynamoDB avoid duplicate non-key attributes

DynamoDB consistent reads for Global Secondary Index

+0

я есть глобальные вторичные индексы, чтобы проверить, если имя пользователя или электронная почта уже существует, но его не Таким образом, если 2 пользователя одновременно запрашивают и получают доступ к электронной почте, они оба вставляются в таблицу users. И если нет проверки, чтобы проверить, нет ли имени/имени пользователя уже, у нас есть повторяющиеся записи для email/username – kishorer747

+0

Я отредактировал ответ. В этом случае вы должны использовать блокировки приложений (например, memcache) –

+0

Да, у меня есть отдельная таблица, которая проверяет уникальность как для имени пользователя, так и для электронной почты. Но в тех случаях, когда 2 пользователя одновременно пытаются зарегистрироваться тот же адрес электронной почты/имя пользователя, он вставляет даже wi th дубликатов. Благодарю. Я посмотрю на замки. – kishorer747

1

Хорошо, я нашел ошибку в своем приложении.

Я пытаюсь сделать условный элемент put в DynamoDB, но я передаю другой первичный ключ, который существует в DynamoDB, и в этот момент будет создан новый объект, а условное выражение будет проигнорировано.

# id primary key 
id = 123 
# email is only index 
email = "[email protected]" 

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}) 

Если вы хотите, чтобы условные выражения работают отлично на DynamoDB put_item вы должны послать тот же первичный ключ, которая существует на БД.

kishorer747, можете ли вы поместить образец своего кода, который сделает это? «У меня есть Глобальные вторичные индексы, чтобы проверить, существует ли имя пользователя или электронные письма , но его не атомарно. Так что если 2 пользователя запросят одновременно и , получите доступный email1, они оба вставляются в таблицу users.И если нет никакой проверки, чтобы проверить, если адрес электронной почты/имя пользователя не существует уже, у нас есть повторяющиеся записи для электронной почты/имя пользователя "

+0

вы можете упомянуть пользователя, чтобы привлечь их внимание следующим образом: @malmeida hello! но вы должны сделать это в комментарии. – yuyoyuppe