Node.js'te DynamoDB Koşullu Yazma (AWS SDK v3)

AWS SDK v3'te koşullu bir yazmanın ilginç kısmı, her yerde aynı çalışan ve DynamoDB koşul ifadeleri sayfasında ele alınan ConditionExpression değildir. İlginç olan başarısızlık yoludur: v3, istediyseniz kaybeden öğeyi fırlatılan hatanın üzerinde size verir, istemediyseniz hiçbir şey vermez.

Kod

import {DynamoDBClient, UpdateItemCommand} from '@aws-sdk/client-dynamodb';

const client = new DynamoDBClient({region: 'us-east-1'});

// Update the item only if nobody changed it since we read version 7.
const command = new UpdateItemCommand({
  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'
});

try {
  await client.send(command);
  console.log('Updated to version 8');
} catch (err) {
  if (err.name === 'ConditionalCheckFailedException') {
    // With ReturnValuesOnConditionCheckFailure: 'ALL_OLD', the current item
    // rides back on the exception — no extra read to see what beat you.
    console.log('Lost the race — item is now:', err.Item);
  } else {
    throw err;
  }
}

Açıklama

  • Başarısız denetim, bir durum alanı değil, fırlatılan bir hatadır. v3 promise'i reddeder; dolayısıyla yazma yolu ile yarışı kaybetme yolu farklı dallardır. err.name === 'ConditionalCheckFailedException' ayırt edicidir; başka her şey yeniden fırlatılmalıdır — bloktaki else bunun içindir. Tüm catch'i yutarsanız bir kısıtlamayı sessizce işlemsiz bir çağrıya dönüştürmüş olursunuz.
  • Sizi kimin geçtiğini görmenin tek yolu ReturnValuesOnConditionCheckFailure'dır. O olmadan hata yalnızca mesajı taşır, başka bir şey taşımaz ve ihtiyacınız olmayan bir GetItem'a geri dönmüş olursunuz. API başvurusu geçerli değerlerini ALL_OLD | NONE olarak belirler ve hiç okuma kapasitesi tüketmediğini doğrular.
  • err.Item ham bir AttributeValue eşlemesidir, gönderdiğiniz Key ile aynı biçimdedir, düz JavaScript değil. Version'ı bir sayıyla karşılaştırmadan önce onu @aws-sdk/util-dynamodb'deki unmarshall'dan geçirin, yoksa {N: '9'} ile karşılaştırıyor olursunuz.
  • Başarısız yazma yine de faturalandırılır. Developer Guide, yanlış değerlendirilen bir koşulun yine de yazma kapasitesi tükettiğini ve bunun eski ile yeni öğeden büyüğüne göre boyutlandığını açıkça söyler. Sıcak bir anahtar üzerindeki bir yeniden deneme döngüsü faturada gerçek bir kalemdir; bu yüzden deneme sayısını sınırlayın.
  • Bloktaki her ad takma adlıdır (#versionVersion, #cond0Artist), çünkü onu üreten Expression Builder koşulsuz olarak takma ad verir. Bu burada gerekenden ağırdır ve asla yanlış değildir — yaptığı takas budur.

Kaybedenin kopyasını istisnadan okumak

Saklanan Version'ı 9 yapın ve 7 bekleyen bloğu çalıştırın. DynamoDB Local 3.3.0 hata fırlatır ve yakalanan hata şunları taşır:

err.name     ConditionalCheckFailedException
err.message  The conditional request failed
err.$metadata.httpStatusCode  400
err.Item     {
               Artist:     { S: 'Arturo Sandoval' },
               Year:       { N: '1994' },
               Version:    { N: '9' },
               SongTitle:  { S: 'Cubano Chant' },
               AlbumTitle: { S: 'Danzon' }
             }

O Version: 9 işin bütün özüdür. Yeniden deneme, :expectedVersion 9 yapılarak doğrudan güncellemeye geri dönebilir — fazladan okuma olmadan ve GetItem'ınız ile yeniden denemeniz arasına üçüncü bir yazarın sızabileceği bir pencere olmadan.

Aynı komuttan ReturnValuesOnConditionCheckFailure'ı silin ve yeniden çalıştırın. Aynı name, aynı message, aynı 400 ve err.Item undefined. Hiçbir şey sizi uyarmaz: parametre isteğe bağlıdır, yokluğu bir hata değildir ve err.Item'ı okuyan kod üretimde undefined günlüklemeye başlar.

Ayrıca buradaki bir 400'ün hatalı biçimlendirilmiş bir istek anlamına gelmediğini de not edin. ValidationException ve ConditionalCheckFailedException aynı durum kodunu paylaşır ve yalnızca biri bir hatadır; dallanmanın durum koduna değil, err.name'e göre olmasının nedeni budur.

Bir koşulun kendi verinize karşı başarılı ve başarısız olmasını, ifadeyi elle yazmak yerine sizin için yazdırarak izlemek için DynoTable'ı indirin.

İlgili örnekler

Kaynaklar

En son 2026-07-28 tarihinde yukarıda bağlantısı verilen resmi AWS belgelerine karşı doğrulandı.

Console olmadan DynamoDB ile çalış

DynamoDB’nin çalıştıramadığı gerçek SQL’i çalıştıran hızlı bir DynamoDB masaüstü istemcisi — JOINs, GROUP BY, toplamalar — görsel düzenleme ve kendi Bedrock anahtarların üzerinde bir yapay zekâ aracısıyla.

30 günlük ücretsiz deneme, kredi kartı yok — ardından süre sınırı olmayan Ücretsiz plan.