Penulisan Bersyarat DynamoDB di Python (boto3)
boto3 adalah satu-satunya SDK yang punya kelas exception bernama untuk ditangkap pada penulisan bersyarat, dan sekaligus satu-satunya yang menyembunyikan item yang dikembalikan di tempat yang tak akan Anda tebak. Expression-nya sendiri bekerja sama di mana pun; condition expression DynamoDB membahas fungsi-fungsinya dan pola optimistic-locking.
Kode
import boto3
client = boto3.client("dynamodb")
# Update the item only if nobody changed it since we read version 7.
try:
client.update_item(
TableName="Music",
Key={"Artist": {"S": "Arturo Sandoval"}, "SongTitle": {"S": "Cubano Chant"}},
UpdateExpression="SET #upd0 = :updValue0, #version = :newVersion",
ConditionExpression="attribute_exists(#cond0) AND #version = :expectedVersion",
ExpressionAttributeNames={"#upd0": "Genre", "#version": "Version", "#cond0": "Artist"},
ExpressionAttributeValues={
":updValue0": {"S": "Latin Jazz"},
":expectedVersion": {"N": "7"},
":newVersion": {"N": "8"},
},
ReturnValuesOnConditionCheckFailure="ALL_OLD",
)
print("Updated to version 8")
except client.exceptions.ConditionalCheckFailedException as e:
# With ReturnValuesOnConditionCheckFailure="ALL_OLD", the current item
# rides back on the exception — no extra read to see what beat you.
print("Lost the race — item is now:", e.response.get("Item"))Penjelasan
ConditionalCheckFailedExceptionadalah kelas yang dimodelkan, jadiexcept client.exceptions.…bekerja. Sebagian besar error DynamoDB tidak begitu:ValidationExceptionsama sekali tak punya kelas dan harus dicocokkan padae.response["Error"]["Code"]. Kelas yang dimodelkan itu tetap merupakan subclass dariClientError, jadiexcept ClientErroryang luas di hulu akan menelannya kalau Anda mengurutkan handler secara serampangan.- Item yang dikembalikan adalah key tingkat atas dari
e.response, bukan darie.response["Error"]. Itulah sebabnya blok kode di atas membacae.response.get("Item"). Gampang sekali mencarinya di bawah["Error"]bersamaCodedanMessage, tidak menemukan apa-apa, lalu menyimpulkan parameternya tidak bekerja. - Item itu kembali dalam DynamoDB JSON meskipun Anda mungkin terbiasa dengan nilai native, karena ini adalah client tingkat rendah.
boto3.dynamodb.types.TypeDeserializermengonversinya kalau Anda mau Python biasa. - Resource API menyatakan penjaga yang sama sebagai objek,
ConditionExpression=Attr("Version").eq(7) & Attr("Artist").exists(), dengan nilai native dan tanpa map placeholder. Ia melemparkan exception yang identik, jadi penanganan di bawah tak berubah. - Pemeriksaan yang gagal tetap menagih satu penulisan. Developer Guide menyatakan dengan jelas bahwa kondisi bernilai false tetap memakan kapasitas tulis, diukur pada item yang lebih besar antara yang lama dan yang baru, jadi percobaan ulang tanpa batas pada key yang diperebutkan menghabiskan uang sungguhan tanpa membuat kemajuan.
Di mana boto3 meletakkan item yang dikembalikan
Jalankan blok kode itu terhadap Version tersimpan bernilai 9 lalu cetak key respons dari exception-nya. DynamoDB Local 3.3.0, boto3 1.43.58:
sorted(e.response.keys()) -> ['Error', 'Item', 'ResponseMetadata']
e.response["Item"] -> {'Artist': {'S': 'Arturo Sandoval'},
'Year': {'N': '1994'},
'Version': {'N': '9'},
'SongTitle': {'S': 'Cubano Chant'},
'AlbumTitle': {'S': 'Danzon'}}Hapus ReturnValuesOnConditionCheckFailure dan kegagalan yang sama memberi ['Error', 'ResponseMetadata']. Key Item tidak ada, dan e.response.get("Item") mengembalikan None alih-alih melempar error. Itulah versi bug ini yang lolos code review dan mulai mencatat None di produksi.
Mengapa setiap nama dalam expression diberi alias
Blok kode itu menulis #version dan #cond0 alih-alih Version dan Artist, yang terlihat berlebihan untuk dua kata biasa. Memang berlebihan, untuk dua kata ini. Version bukan reserved word DynamoDB, dan dipakai apa adanya ia lolos validasi nama.
Year termasuk reserved, dan tabel yang sama punya atribut itu. Jaga langsung pada atribut itu dan Anda mendapat:
ValidationException: Invalid ConditionExpression: Attribute name is a reserved keyword;
reserved keyword: YearAda 573 kata dalam daftar itu, termasuk Name, Status, Size, Count, Data, Owner, Timestamp dan Items. Memberi alias pada semuanya adalah cara kode yang dihasilkan menghindari keharusan tahu mana yang mana. Tempelkan nama atribut Anda ke pemeriksa reserved word dan ia mengembalikan map ExpressionAttributeNames untuk nama-nama yang membutuhkannya.
Untuk menulis penjaga ini terhadap tabel Anda sendiri dengan pemberian alias yang diurus untuk Anda, unduh DynoTable.
Contoh terkait
- Penulisan bersyarat DynamoDB di Node.js — optimistic lock yang sama dengan AWS SDK v3.
- Penulisan bersyarat DynamoDB dengan AWS CLI — optimistic lock yang sama dari shell.
- DynamoDB PutItem di Python — put
attribute_not_existsyang hanya membuat. - Condition expression DynamoDB — setiap fungsi, lengkap dengan polanya.
- Menegakkan keunikan pada beberapa atribut — kondisi + transaksi digabungkan.
- DynamoDB ConditionalCheckFailedException — kapan pemeriksaan yang gagal itu memang diharapkan, dan cara menanganinya dengan murah.
Referensi
- UpdateItem — Amazon DynamoDB API Reference
- DynamoDB.Client.update_item — Boto3 documentation
- Condition expressions — Amazon DynamoDB Developer Guide
- DynamoDB read and write operations (capacity unit consumption) — Amazon DynamoDB Developer Guide
- Reserved words in DynamoDB — Amazon DynamoDB Developer Guide
Terakhir diverifikasi 2026-07-28 terhadap dokumentasi resmi AWS yang ditautkan di atas.