web-dev-qa-db-ja.com

boto3を使用してdynamodbテーブルに条件付きでアイテムを挿入する方法

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を持つアイテムが存在するかどうか。

19
aychedee

残念ながら、このドキュメントはあまり明確ではありません。同様のことを達成する必要がありましたが、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関数にありますが、最初にそれを機能させる方法は明確ではありませんでした。いくつかの実験の後、私は上記でうまくいくことができました。

54
jimjkelly

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
5
Venkat.V.S

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

2
Eyal Ch