2015-07-08 7 views
8

Ich benutze DynamoDB als K-V db (weil es nicht viele Daten gibt, ich denke, das ist in Ordnung), und ein Teil von 'V' ist Listentyp (etwa 10 Elemente). Es gibt eine Sitzung, um einen neuen Wert anzuhängen, und ich kann keinen Weg finden, dies in 1 Anfrage zu tun. Was ich gemacht habe ist wie folgt:Wie fügt man einen Wert zum Listenattribut in AWS DynamoDB hinzu?

item = self.list_table.get_item(**{'k': 'some_key'}) 
item['v'].append('some_value') 
item.partial_save() 

Ich fordere den Server zuerst und speichern Sie es, nachdem Sie den Wert geändert haben. Das ist nicht atomar und sieht hässlich aus. Gibt es eine Möglichkeit, dies in einer Anfrage zu tun?

Antwort

3

Sie können dies in 1 Anfrage mit dem UpdateItem API in Verbindung mit einem UpdateExpression tun. Da Sie auf eine Liste angehängt werden soll, würden Sie die SET Aktion mit der list_append Funktion:

SET unterstützt die folgenden Funktionen:

...

  • list_append (operand, operand) - ausgewertet ein Liste mit einem neuen Element hinzugefügt. Sie können das neue Element am Anfang oder am Ende der Liste anhängen, indem Sie die Reihenfolge der Operanden umkehren.

Sie können ein paar Beispiele dafür auf dem Modifying Items and Attributes with Update Expressions documentation sehen:

  • Im folgenden Beispiel wird ein neues Element in die Fivestar Revisionsliste. Der Ausdruck Attributname #pr ist ProductReviews; Das Attribut Wert :r ist eine Ein-Element-Liste. Wenn die Liste zuvor zwei Elemente , [0] und [1] hatte, wird das neue Element [2] sein.

    SET #pr.FiveStar = list_append(#pr.FiveStar, :r) 
    
  • Das folgende Beispiel fügt ein weiteres Element in die Liste Fivestar Bewertung, aber dieses Mal wird das Element bei [0] zu Beginn der Liste angehängt werden. Alle anderen Elemente in der Liste werden um eins verschoben.

    SET #pr.FiveStar = list_append(:r, #pr.FiveStar) 
    

Die #pr und :r verwenden Platzhalter für die Attributnamen und Werte. Sie können weitere Informationen zu denen auf der Using Placeholders for Attribute Names and Values documentation sehen.

+0

Aber ich keine API in Boto gefunden ... – kxxoling

24

Der folgende Code mit boto3 funktionieren sollte:

table = get_dynamodb_resource().Table("table_name") 
result = table.update_item(
    Key={ 
     'hash_key': hash_key, 
     'range_key': range_key 
    }, 
    UpdateExpression="SET some_attr = list_append(some_attr, :i)", 
    ExpressionAttributeValues={ 
     ':i': [some_value], 
    }, 
    ReturnValues="UPDATED_NEW" 
) 
if result['ResponseMetadata']['HTTPStatusCode'] == 200 and 'Attributes' in result: 
    return result['Attributes']['some_attr'] 

Die get_dynamodb_resource Methode hier ist einfach:

def get_dynamodb_resource(): 
    return boto3.resource(
      'dynamodb', 
      region_name=os.environ['AWS_DYNAMO_REGION'], 
      endpoint_url=os.environ['AWS_DYNAMO_ENDPOINT'], 
      aws_secret_access_key=os.environ['AWS_SECRET_ACCESS_KEY'], 
      aws_access_key_id=os.environ['AWS_ACCESS_KEY_ID']) 
+0

danke! das funktioniert perfekt. Obwohl ich ADD versuchte, aber das hat nicht funktioniert. Ich habe in den Dokumenten gelesen, dass sie ADD empfehlen. Als ich versucht habe, ADD zu verwenden, habe ich einen Operator-Mismatch-Fehler in UpdateExpression bekommen. – kishorer747

+0

Sehr nützlich! Tut mir leid, ich kann nur +1 tun :( – vnpnlz

+0

muss das Listenelement existieren? Oder kann ich das einfach verwenden und es wird some_attr für mich als leere Liste initiieren, wenn es nicht existiert? – Jonathan