it-swarm.com.de

Wie füge ich ein Element mit boto3 bedingt in eine dynamodb-Tabelle ein?

Wenn ich eine Tabelle mit einem Hash-Schlüssel von userId und einem Bereichsschlüssel von productId habe, wie füge ich ein Element nur dann in diese Tabelle ein, wenn es nicht bereits mit den Dynamodb-Bindungen von boto3 existiert?

Der normale Aufruf von put_item sieht so aus

table.put_item(Item={'userId': 1, 'productId': 2})

Mein Aufruf mit einer ConditionExpression sieht folgendermaßen aus:

table.put_item(
    Item={'userId': 1, 'productId': 2}, 
    ConditionExpression='userId <> :uid AND productId <> :pid', 
    ExpressionAttributeValues={':uid': 1, ':pid': 3}
)

Dies führt jedoch jedes Mal zu einer ConditionalCheckFailedException. Ob ein Artikel mit derselben productId existiert oder nicht. 

13
aychedee

Die Dokumentation dazu ist leider nicht sehr klar. Ich musste etwas Ähnliches erreichen, und mit boto3 funktionierte es für mich:

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

Ähnlich wie bei der anderen Antwort liegt der Schlüssel in der Funktion attribute_not_exists, aber mir war zunächst unklar, wie das funktioniert. Nach einigem Experimentieren konnte ich es mit dem oben Gesagten in Gang bringen.

39
jimjkelly

ich denke, Sie erhalten eine bessere Dokumentation mit client.put_item anstelle von table.put_item

aus boto3 Dokumentation :

Um zu verhindern, dass ein neues Element ein vorhandenes Element ersetzt, verwenden Sie einen Bedingungsausdruck, der die Funktion attribute_not_exists mit dem Namen des Attributs enthält, das als Partitionsschlüssel für die Tabelle verwendet wird. Da jeder Datensatz dieses Attribut enthalten muss, ist die Funktion attribute_not_exists nur erfolgreich, wenn kein übereinstimmendes Element vorhanden ist.

ConditionExpression:

ConditionExpression (string) - Eine Bedingung, die in .__ erfüllt sein muss. bestellen, damit eine bedingte PutItem-Operation erfolgreich ausgeführt werden kann.

Ein Ausdruck kann Folgendes enthalten:

Funktionen: attribute_exists | attribute_not_exists | Attributtyp | enthält | beginnt_mit | size Diese Funktionsnamen unterscheiden zwischen Groß- und Kleinschreibung.

ich verwende dynamodb2 Überschreibungsparameter on item.save()

2
Eyal Ch

Sie benötigen keinen Sortierschlüssel (oder Bereichsschlüssel), nur der Partitionsschlüssel oder der Hash-Schlüssel reicht aus.

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