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が発生します。同じproductIdを持つアイテムが存在するかどうか。
残念ながら、このドキュメントはあまり明確ではありません。同様のことを達成する必要がありましたが、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関数にありますが、最初にそれを機能させる方法は明確ではありませんでした。いくつかの実験の後、私は上記でうまくいくことができました。
Sortkey(または範囲キー)は必要ありません。パーティションキーまたはハッシュキーで十分です。
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
table.put_itemではなくclient.put_itemを使用すると、より良いドキュメントが得られると思います。
boto3から ドキュメント :
新しいアイテムが既存のアイテムを置き換えないようにするには、attribute_not_exists関数を含む条件式を使用し、テーブルのパーティションキーとして使用される属性の名前を指定します。すべてのレコードにはその属性が含まれている必要があるため、attribute_not_exists関数は、一致するアイテムが存在しない場合にのみ成功します。
条件式:
ConditionExpression(文字列)-条件付きPutItem操作が成功するために満たす必要がある条件。
式には、次のいずれかを含めることができます。
関数:attribute_exists | attribute_not_exists | attribute_type |含む| begins_with | sizeこれらの関数名では大文字と小文字が区別されます。
私はdynamodb2を使用しています パラメータを上書き on item.save()