Как условно вставить элемент в таблицу dynamodb с помощью boto3
Если у меня есть таблица с хэш-ключом userId и ключ диапазона productId, как я могу поместить элемент в эту таблицу, только если он еще не существует с помощью привязок boto3 dynamodb?
Обычный вызов put_item выглядит следующим образом:
table.put_item(Item={'userId': 1, 'productId': 2})
Мой вызов с выражением ConditionExpression выглядит так:
table.put_item(
Item={'userId': 1, 'productId': 2},
ConditionExpression='userId <> :uid AND productId <> :pid',
ExpressionAttributeValues={':uid': 1, ':pid': 3}
)
Но каждый раз возникает исключение ConditionalCheckFailedException. Существует ли элемент с одним и тем же продуктом или нет.
Ответы
Ответ 1
Документация для этого, к сожалению, не очень понятна. Мне нужно было что-то сделать, и вот что для меня работало, используя 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
Подобно другому ответу, ключ находится в функции attribute_not_exists, но сначала мне было непонятно, как заставить это работать. После некоторых экспериментов я смог добиться этого.
Ответ 2
Я думаю, что вы получите лучшую документацию, используя client.put_item, а не table.put_item
из документации boto3:
Чтобы предотвратить замену нового элемента на существующий элемент, используйте условное выражение, содержащее функцию attribute_not_exists, с именем атрибута, используемого в качестве ключа раздела для таблицы. Поскольку каждая запись должна содержать этот атрибут, функция attribute_not_exists будет успешной только в том случае, если соответствующий элемент не существует.
ConditionExpression:
ConditionExpression (string) - условие, которое должно выполняться для успешного выполнения операции условного ввода.
Выражение может содержать любое из следующего:
Функции: attribute_exists | attribute_not_exists | attribute_type | содержит | begin_with | size Эти имена функций чувствительны к регистру.
Я использую параметр переопределения item.save()
на item.save()