2013-08-08 5 views
5

Ich versuche put_item zu haben, um zu prüfen, ob es einen Artikel mit demselben HashKey gibt, bevor der neue Artikel tatsächlich hinzugefügt wird.Boto DynamoDB2 konditional put_item

Laut boto DynamoDB2 Dokument ist es möglich, es mit "Conditional Put" zu tun.

Ich versuchte folgenden Befehl, aber kein Glück.

connection.put_item('table',item={'locationId':'a1', 'timestamp': time.time()}, expected={'locationID':False}) 

Die Fehlermeldung lautet wie folgt.

boto.exception.JSONResponseError: JSONResponseError: 400 Bad Request 
{u'Message': u'Expected null', u'__type': u'com.amazon.coral.service#SerializationException'} 

Hat jemand eine bedingte Put mit DynamoDBv2?

Vielen Dank an alle im Voraus.

+0

Sie können DynamoDB anweisen, das Element nur zu speichern, wenn nicht bereits ein Element mit demselben Primärschlüssel vorhanden ist. In diesem Fall müsste die '' expected''-Klausel auf diesen Primärschlüssel und nicht auf '' False' 'verweisen '. – garnaat

+0

@garnaat, Vielen Dank für den Kommentar. Ich denke, dass es mehrere Fehler geben kann. Ich habe den Befehl auch ohne 'expected' Teil ausprobiert und trotzdem den gleichen Fehler erhalten -' boto.exception.JSONResponseError: JSONResponseError: 400 Ungültige Anfrage {u'Message ': u'Expected null', u '__ type': u'com .amazon.coral.service # SerializationException '} '. Ich frage mich, ob es irgendwelche bedingten 'put_item()' Beispiele gibt, die ich mir ansehen kann ... Ich habe versucht, Google zu suchen, aber kein Glück. – nicklee

+0

@garnaat Haben Sie Beispielcodes, die mit DynamodB v2 funktionieren? – nicklee

Antwort

6

Sie müssen es so schreiben, damit die Syntax funktioniert. Es ist extrem schlecht, dass dies nirgendwo dokumentiert ist. Ich hatte genau das gleiche Problem und musste 50 verschiedene Dinge ausprobieren, während ich die Java SDK-Dokumentation durchforstete, damit es funktionierte. Beachten Sie, dass Sie einen Wert angeben müssen, wenn Sie mit 'Exists': True anstelle von False gehen möchten.

connection.put_item(
    'table', 
    item={ 
     'locationId':{'S': 'a1'}, 
     'timestamp': {'N': str(time.time()) 
    }, 
    expected={ 
     'locationID': {'Exists': False} 
    } 
    #expected={ 
    # 'locationID': {'Exists': True, 'Value': {'N': '0'}} 
    #} 
) 

Hoffe es hilft!

Edit: the question that helped me with the syntax enough to make it work und code in the boto integration tests

+0

Ich habe versucht, den von Ihnen bereitgestellten Code zu verwenden, aber "TypeError: put_item() hat ein unerwartetes Schlüsselwortargument erwartet". Ohne expected-Klausel funktioniert es (gibt item ein und gibt true zurück). – nicklee

+0

Es sollte "erwartet" werden, nicht "erwartet" :) – moodh

+0

Sorry, ich habe die falsche Fehlermeldung verwendet. Auch bei 'erwartet‘ Ich bekomme die gleichen Fehler wie folgend ... Traceback (jüngste Aufforderung zuletzt): File ‚‘, Zeile 6, in Typeerror: put_item() bekam ein unerwartetes Stichwort Argument ‚erwartet‘ – nicklee

0

Beachten Sie, dass der Parameter expected von put_item ist jetzt deprecated:

Parameters: expected (map)

There is a newer parameter available. Use ConditionExpression instead.

Verwenden condition_expression statt:

connection.put_item(
    'table', 
    item={ 
     'locationId': {'S': 'a1'}, 
     'timestamp': {'S': str(time.time())} 
    }, 
    condition_expression='attribute_exists(locationId)' 
) 

Es ist auch möglich, Kettenausdrücke und benannte Parameter verwenden, zB:

connection.put_item(
    'table', 
    item={ 
     'locationId': {'S': 'a1'}, 
     'timestamp': {'S': str(time.time())} 
    }, 
    condition_expression=(
     'attribute_exists(locationId) AND ' 
     'NOT attribute_type(locationId, :expected_type)' 
    ), 
    expression_attribute_values={ 
     ':expected_type': {'S': 'NULL'} # String parameter of value 'NULL' 
    } 
) 

See Performing Conditional Writes with Condition Expressions for more details.