web-dev-qa-db-fra.com

Comment insérer conditionnellement un élément dans une table dynamodb avec l'aide de boto3

Si j'ai une table avec une clé de hachage userId et une clé de plage de productId, comment puis-je insérer un élément dans cette table uniquement s'il n'existe pas déjà à l'aide des liaisons dynamodb de boto3?

L'appel normal à put_item ressemble à ceci

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

Mon appel avec une ConditionExpression ressemble à ceci:

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

Mais cela déclenche une exception ConditionalCheckFailedException à chaque fois. Si un article existe avec le même productId ou non. 

13
aychedee

La documentation pour cela n'est malheureusement pas très claire. J'avais besoin d'accomplir quelque chose de similaire, et voici ce qui a fonctionné pour moi, en utilisant 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

Semblable à l’autre réponse, la clé se trouve dans la fonction attribute_not_exists, mais j’ignorais au début comment faire fonctionner cela. Après quelques expériences, j'ai pu le faire avec ce qui précède.

39
jimjkelly

je pense que vous obtiendrez une meilleure documentation en utilisant client.put_item plutôt que table.put_item

de boto3 documentation :

Pour empêcher un nouvel élément de remplacer un élément existant, utilisez une expression conditionnelle contenant la fonction attribute_not_exists avec le nom de l'attribut utilisé comme clé de partition pour la table. Étant donné que chaque enregistrement doit contenir cet attribut, la fonction attribut_not_existe ne réussira que si aucun élément correspondant n'existe.

ConditionExpression:

ConditionExpression (string) - Une condition qui doit être remplie dans pour qu'une opération PutItem conditionnelle aboutisse.

Une expression peut contenir l'un des éléments suivants:

Fonctions: attribut_exists | attribut_not_existe | type_attribut | contient | commence_avec | taille Ces noms de fonctions sont sensibles à la casse.

j'utilise dynamodb2 écrase le paramètre sur item.save()

2
Eyal Ch

Vous n'avez pas besoin de la clé de tri (ou clé de plage), seule la clé de partition ou la clé de hachage suffit.

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