Intermedio6 min de lectura

DynamoDB Actualizar expresiones: SET, REMOVE, ADD, DELETE (con ejemplos)

Una expresión de actualización le dice a UpdateItem cómo mutar un solo elemento: cuál para escribir, incrementar, eliminar o plegar en un conjunto. No hay varias filas UPDATE … SET … WHERE: nombras un solo elemento por su clave completa y describe el cambie con la clave de cuatro cláusulasrds.

¿Cómo funcionan las DynamoDB expresiones de actualización?

Una expresión de actualización DynamoDB le dice a UpdateItem cómo mutar un elemento usando cuatro cláusulas. SET escribe o sobrescribe un . ADD incrementa atómicamente un número o uniones en un conjunto. REMOVE elimina un atributo o un elemento de la lista. DELETE elimina miembros específicos de un conjunto. Una llamada puede transportar los cuatro a la vez.

  • SET escribe o sobrescribe un atributo: escalares, documentos y el modismos de función if_not_exists y list_append.
  • ADD hace un incremento de número atómico o una unión de conjunto, en un viaje de ida y vuelta, sin lectura primero.
  • REMOVE elimina un atributo directamente (o un único elemento de lista por índice).
  • DELETE elimina miembros específicos de un conjunto, y solo de un conjunto.

Viniendo de SQL, la trampa busca SET para todo. ADD y DELETE existen porque leer-modificar-escribir en un contador o un conjunto es una carrera que perder bajo concurrencia.

Elige la cláusula según lo que estás cambiando

Una llamada UpdateItem puede llevar las cuatro cláusulas a la vez, en cualquier orden. cada uno La palabra clave aparece como máximo una vez y requiere una lista de acciones separadas por comas.

CláusulaTrabaja enÚselo para
SETCualquier atributoEscribir/sobrescribir un valor o campo de documento
ADDSolo número o conjuntoIncremento atómico o unión en un conjunto
REMOVECualquier atributo o elemento de listaEliminar un atributo; soltar un índice de lista
DELETEEstablecer soloEliminar miembros específicos de un conjunto

ADD en una cadena y DELETE en un escalar son errores de validación, no operaciones no operativas. DynamoDB rechaza toda la llamada. Según el AWS referencia de expresión de actualización, ADD está restringido a números y conjuntos, y DELETE a conjuntos.

El ejemplo resuelto: un carrito de compras

Un artículo por carrito, codificado por CartPK = "CART#c-9f21" y CartSK = "SUMMARY". Realiza un seguimiento de una lista OrderTotal en ejecución, una lista LineItems, un conjunto de cadenas PromoCodes, y un ItemCount.

SET: escribe los escalares y los documentos

SET sobrescribe lo que haya allí. Agregue una línea de pedido a la lista y elimine el total en la misma convocatoria:

SET OrderTotal = :total,
LineItems = list_append(LineItems, :newItem),
UpdatedAt = :now

list_append(LineItems, :newItem) añade al final; invierte los argumentos — list_append(:newItem, LineItems) — para añadir al principio. El orden de los argumentos es el orden de la concatenación, nada más.

Hay una trampa en esa primera llamada: si el carrito es nuevo, LineItems todavía no existe, y list_append sobre un atributo ausente falla. Protégelo con if_not_exists:

SET LineItems = list_append(if_not_exists(LineItems, :empty), :newItem)

if_not_exists(LineItems, :empty) devuelve la lista actual si existe, y si no el valor de reserva :empty (una lista vacía []). Eso hace que la primera adición y todas las posteriores usen la misma expresión: una razón real de que existan estos modismos.

ADD — incrementa el recuento, de forma atómica

Para subir ItemCount, no lo leas, sumes uno en tu código y lo vuelvas a escribir con SET. Eso es una carrera de actualización perdida: dos adiciones concurrentes leen 3, ambas escriben 4 y has perdido una. ADD hace la aritmética en el lado del servidor:

ADD ItemCount :one

Con :one = 1, esto es un contador atómico. Las llamadas concurrentes se serializan sobre el elemento, así que dos adiciones aterrizan como +2. Pasa un número negativo para decrementar. Si ItemCount no existe, ADD lo trata primero como 0, así que nunca necesitas inicializar el contador.

Bajo demanda en us-east-1, cada ADD factura 1 WCU por KB del elemento después de la escritura (redondeado hacia arriba). Un resumen de carrito de 1 KB con un ADD ItemCount :one cuesta 1 WCU: la misma fila con un SET de leer-modificar-escribir costaría los mismos WCU pero perdería bajo concurrencia. Dimensiona el elemento en la calculadora de tamaño de elemento.

Puedes construir esta misma expresión — nombres, valores tipados y la petición marshalled — en el generador de expresiones de DynamoDB sin escapar a mano ni un solo marcador #name o :value.

Edita el preajuste de abajo — un SET más un ADD atómico — y observa cómo se reconstruye la UpdateExpression sobre la marcha:

Construye tu solicitud
Código generado
new UpdateItemCommand({
  "TableName": "AuditLog",
  "Key": {
    "pk": {
      "S": "TENANT#acme"
    },
    "sk": {
      "S": "CONFIG"
    }
  },
  "UpdateExpression": "SET #upd0 = :updValue0 ADD #upd1 :updValue1",
  "ExpressionAttributeNames": {
    "#upd0": "plan",
    "#upd1": "seats"
  },
  "ExpressionAttributeValues": {
    ":updValue0": {
      "S": "pro"
    },
    ":updValue1": {
      "N": "5"
    }
  }
})

REMOVE — elimina un atributo o una línea de pedido

REMOVE es como se borra un atributo por completo (no existe el "ponlo a null": eso solo escribe un tipo NULL). Borra un descuento aplicado y elimina la tercera línea de pedido en una sola llamada:

REMOVE AppliedDiscount, LineItems[2]

LineItems[2] elimina el elemento del índice 2 y desplaza hacia abajo todo lo que va detrás: el índice 3 pasa a ser 2, y así sucesivamente. Si haces REMOVE de dos índices en una misma expresión, ambos se evalúan contra la lista original, así que eliminar [2] y [3] juntos quita el tercer y el cuarto elemento, como esperarías.

DELETE — quita miembros de un conjunto

PromoCodes es un conjunto de cadenas, así que un cliente que retira un código usa DELETE, no REMOVE. REMOVE PromoCodes arrasaría con el conjunto entero; DELETE resta los miembros nombrados:

DELETE PromoCodes :pulled

Con :pulled = el conjunto {"SAVE10"}, solo se va ese miembro. Aquí muerden dos reglas: un conjunto nunca puede estar vacío, así que borrar el último miembro elimina el atributo PromoCodes por completo; y el valor debe ser un tipo conjunto que coincida con el atributo — una cadena suelta es un error de tipo.

Júntalo todo

Una actualización de "añade el artículo, aplica una promoción, sube el recuento" es una sola llamada repartida en tres cláusulas:

SET LineItems = list_append(if_not_exists(LineItems, :empty), :newItem),
OrderTotal = OrderTotal + :price
ADD ItemCount :one
DELETE PromoCodes :expiredCode

Fíjate en OrderTotal = OrderTotal + :price: la aritmética dentro de SET opera sobre el valor existente. Es igual de atómica y segura frente a carreras que ADD: DynamoDB evalúa OrderTotal + :price en el lado del servidor contra el valor actual, así que las llamadas concurrentes se serializan sobre el elemento en lugar de dar un rodeo por tu código.

Escollos a evitar

  • Hacer SET de un contador que has leído antes. Usa ADD: leer-modificar-escribir pierde actualizaciones bajo concurrencia. Es el error de carrito/inventario más común.
  • list_append sobre una lista ausente. Envuelve el destino en if_not_exists o la primera escritura falla.
  • Confundir REMOVE y DELETE. REMOVE elimina el atributo; DELETE resta miembros de un conjunto. Mezclarlos borra más de lo que pretendías.
  • Olvidar que UpdateItem es un upsert. Si la clave no existe, crea el elemento. Usa una ConditionExpression (attribute_exists(CartPK)) cuando quieras decir "solo actualizar".

Para modelar las claves con las que se ejecutan estas expresiones, consulte diseño de tabla única; para decidir cómo leerás el carrito de vuelta, vea query vs scan.

Construya y copie cualquiera de estos en el generador de expresiones, luego pruebe DynoTable para ejecutarlos en sus propias tablas y observar el elemento. cambiar en vivo.

Actualizado