

# Uso de expresiones de actualización en DynamoDB
<a name="Expressions.UpdateExpressions"></a>

La acción `UpdateItem` actualiza un elemento existente o agrega uno nuevo a la tabla, si no existe ya. Es preciso proporcionar la clave del elemento que se desea actualizar. Asimismo, debe proporcionar una expresión de actualización que indique los atributos que se van a modificar y los valores que se les asignarán. 

Una *expresión de actualización* especifica cómo `UpdateItem` modificará los atributos de un elemento; por ejemplo, estableciendo un valor escalar o eliminando elementos de una lista o un mapa.

A continuación se muestra un resumen de la sintaxis de las expresiones de actualización.

```
update-expression ::=
    [ SET action [, action] ... ]
    [ REMOVE action [, action] ...]
    [ ADD action [, action] ... ]
    [ DELETE action [, action] ...]
```

Una expresión de actualización consta de una o varias cláusulas. Cada cláusula comienza con una palabra clave `SET`, `REMOVE`, `ADD` o `DELETE`. Puede incluir cualquiera de estas cláusulas en una expresión de actualización, en cualquier orden. Sin embargo, cada palabra clave de acción solo puede aparecer una vez.

Cada cláusula contiene una o más acciones, separadas por comas. Cada acción representa una modificación de datos.

Los ejemplos que aparecen en esta sección se basan en el elemento `ProductCatalog` que se muestra en [Uso de expresiones de proyección en DynamoDB](Expressions.ProjectionExpressions.md).

En los temas siguientes se describen algunos casos de uso diferentes de la acción `SET`.

**Topics**
+ [SET: modificación o adición de atributos de elemento](#Expressions.UpdateExpressions.SET)
+ [REMOVE: eliminación de atributos de un elemento](#Expressions.UpdateExpressions.REMOVE)
+ [ADD: actualización de números y conjuntos](#Expressions.UpdateExpressions.ADD)
+ [DELETE: eliminación de elementos de un conjunto](#Expressions.UpdateExpressions.DELETE)
+ [Uso de varias expresiones de actualización](#Expressions.UpdateExpressions.Multiple)

## SET: modificación o adición de atributos de elemento
<a name="Expressions.UpdateExpressions.SET"></a>

Utilice la acción `SET` en una expresión de actualización para agregar uno o varios atributos a un elemento. Si cualquiera de estos atributos ya existe, se sobrescribirá con los nuevos valores. Si desea evitar sobrescribir un atributo existente, puede utilizar `SET` con la función `if_not_exists`. La función `if_not_exists` es específica de la acción `SET` y solamente se puede utilizar en una expresión de actualización.

Cuando se utiliza `SET` para actualizar una entrada de lista, el contenido de esa entrada se sustituye por los nuevos datos que ha especificado. Si el componente no existe, `SET` adjunta el nuevo componente al final de la lista.

Si agrega varias entradas en una misma operación `SET`, las entradas se ordenan según su número.

También puede utilizar `SET` para sumar o restar un valor de un atributo de tipo `Number`. Para llevar a cabo varias acciones `SET`, debe separarlas por comas.

En el resumen de sintaxis siguiente:
+ El componente *path* es la ruta de documento del elemento.
+ Un componente **operand** puede ser una ruta de documento a un elemento o una función.

```
set-action ::=
    path = value

value ::=
    operand
    | operand '+' operand
    | operand '-' operand

operand ::=
    path | function

function ::=
    if_not_exists (path, value)
```

Si el elemento no contiene un atributo en la ruta especificada, `if_not_exists` se evalúa en `value`. De lo contrario, se evalúa como `path`.

La siguiente operación `PutItem` crea un elemento de muestra al que se refieren los ejemplos.

```
aws dynamodb put-item \
    --table-name ProductCatalog \
    --item file://item.json
```

Los argumentos de `--item` se almacenan en el archivo `item.json`. Para simplificar, se utilizan tan solo algunos de los atributos de elementos.

```
{
    "Id": {"N": "789"},
    "ProductCategory": {"S": "Home Improvement"},
    "Price": {"N": "52"},
    "InStock": {"BOOL": true},
    "Brand": {"S": "Acme"}
}
```

**Topics**
+ [Modificación de atributos](#Expressions.UpdateExpressions.SET.ModifyingAttributes)
+ [Adición de listas y mapas](#Expressions.UpdateExpressions.SET.AddingListsAndMaps)
+ [Adición de elementos a una lista](#Expressions.UpdateExpressions.SET.AddingListElements)
+ [Adición de atributos de mapa anidados](#Expressions.UpdateExpressions.SET.AddingNestedMapAttributes)
+ [Aumento y reducción de atributos numéricos](#Expressions.UpdateExpressions.SET.IncrementAndDecrement)
+ [Adición de elementos a una lista](#Expressions.UpdateExpressions.SET.UpdatingListElements)
+ [Cómo evitar sobrescribir un atributo existente](#Expressions.UpdateExpressions.SET.PreventingAttributeOverwrites)

### Modificación de atributos
<a name="Expressions.UpdateExpressions.SET.ModifyingAttributes"></a>

**Example**  
Actualice los atributos `ProductCategory` y `Price`.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET ProductCategory = :c, Price = :p" \
    --expression-attribute-values file://values.json \
    --return-values ALL_NEW
```
Los argumentos de `--expression-attribute-values` se almacenan en el archivo `values.json`.  

```
{
    ":c": { "S": "Hardware" },
    ":p": { "N": "60" }
}
```

**nota**  
En la operación `UpdateItem`, `--return-values ALL_NEW` hace que DynamoDB devuelva el elemento tal y como aparece después de la actualización.

### Adición de listas y mapas
<a name="Expressions.UpdateExpressions.SET.AddingListsAndMaps"></a>

**Example**  
Agregue una lista y un mapa nuevos.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET RelatedItems = :ri, ProductReviews = :pr" \
    --expression-attribute-values file://values.json \
    --return-values ALL_NEW
```
Los argumentos de `--expression-attribute-values` se almacenan en el archivo `values.json`.  

```
{
    ":ri": {
        "L": [
            { "S": "Hammer" }
        ]
    },
    ":pr": {
        "M": {
            "FiveStar": {
                "L": [
                    { "S": "Best product ever!" }
                ]
            }
        }
    }
}
```

### Adición de elementos a una lista
<a name="Expressions.UpdateExpressions.SET.AddingListElements"></a>

**Example**  
Agregue un nuevo atributo a la lista `RelatedItems`. Recuerde que las entradas de lista están basadas en cero; es decir, [0] representa la primera entrada de la lista, [1] representa la segunda, y así sucesivamente.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET RelatedItems[1] = :ri" \
    --expression-attribute-values file://values.json \
    --return-values ALL_NEW
```
Los argumentos de `--expression-attribute-values` se almacenan en el archivo `values.json`.  

```
{
    ":ri": { "S": "Nails" }
}
```

**nota**  
Cuando se utiliza `SET` para actualizar una entrada de lista, el contenido de esa entrada se sustituye por los nuevos datos que ha especificado. Si el componente no existe, `SET` adjunta el nuevo componente al final de la lista.  
Si agrega varias entradas en una misma operación `SET`, las entradas se ordenan según su número.

### Adición de atributos de mapa anidados
<a name="Expressions.UpdateExpressions.SET.AddingNestedMapAttributes"></a>

**Example**  
Agregue algunos atributos de mapa anidados.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET #pr.#5star[1] = :r5, #pr.#3star = :r3" \
    --expression-attribute-names file://names.json \
    --expression-attribute-values file://values.json \
    --return-values ALL_NEW
```
Los argumentos de `--expression-attribute-names` se almacenan en el archivo `names.json`.  

```
{
    "#pr": "ProductReviews",
    "#5star": "FiveStar",
    "#3star": "ThreeStar"
}
```
Los argumentos de `--expression-attribute-values` se almacenan en el archivo `values.json`.  

```
{
    ":r5": { "S": "Very happy with my purchase" },
    ":r3": {
        "L": [
            { "S": "Just OK - not that great" }
        ]
    }
}
```

**importante**  
No puede actualizar los atributos de mapa anidados si el mapa principal no existe. Si intenta actualizar un atributo anidado (por ejemplo, `ProductReviews.FiveStar`) cuando el mapa principal (`ProductReviews`) no existe, DynamoDB devuelve un elemento `ValidationException` con el mensaje *«The document path provided in the update expression is invalid for update»*.  
Al crear elementos cuyos atributos de mapa anidados se vayan a actualizar más adelante, inicialice los mapas vacíos para los atributos principales. Por ejemplo:  

```
{
    "Id": {"N": "789"},
    "ProductReviews": {"M": {}},
    "Metadata": {"M": {}}
}
```
Esto le permite actualizar los atributos anidados como `ProductReviews.FiveStar` sin errores.

### Aumento y reducción de atributos numéricos
<a name="Expressions.UpdateExpressions.SET.IncrementAndDecrement"></a>

Puede sumar o restar un valor a un atributo numérico. Para ello, se utilizan los operadores `+` (más) y `-` (menos).

**Example**  
Reduzca el `Price` de un elemento.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET Price = Price - :p" \
    --expression-attribute-values '{":p": {"N":"15"}}' \
    --return-values ALL_NEW
```
Para aumentar el valor de `Price`, se utiliza el operador `+` en la expresión de actualización.

### Adición de elementos a una lista
<a name="Expressions.UpdateExpressions.SET.UpdatingListElements"></a>

Puede agregar componentes al final de una lista. Para ello, se utiliza `SET` con la función `list_append`. (El nombre de la función distingue entre mayúsculas y minúsculas). La función `list_append` es específica de la acción `SET` y solamente se puede utilizar en una expresión de actualización. La sintaxis es la siguiente.
+ `list_append (list1, list2)`

La función toma dos listas como entrada y anexa todos los elementos de `list2` a ` list1`.

**Example**  
En [Adición de elementos a una lista](#Expressions.UpdateExpressions.SET.AddingListElements), ha creado la lista `RelatedItems` y ha incluido en ella dos componentes: `Hammer` y `Nails`. Ahora, va a agregar dos componentes más al final de `RelatedItems`.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET #ri = list_append(#ri, :vals)" \
    --expression-attribute-names '{"#ri": "RelatedItems"}' \
    --expression-attribute-values file://values.json  \
    --return-values ALL_NEW
```
Los argumentos de `--expression-attribute-values` se almacenan en el archivo `values.json`.  

```
{
    ":vals": {
        "L": [
            { "S": "Screwdriver" },
            {"S": "Hacksaw" }
        ]
    }
}
```
Por último, vamos a agregar un componente más al *principio* de `RelatedItems`. Para ello, invierta el orden de los componentes de `list_append`. (Recuerde que `list_append` toma dos listas como información de entrada y agrega la segunda lista a la primera).  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET #ri = list_append(:vals, #ri)" \
    --expression-attribute-names '{"#ri": "RelatedItems"}' \
    --expression-attribute-values '{":vals": {"L": [ { "S": "Chisel" }]}}' \
    --return-values ALL_NEW
```
Ahora, el atributo `RelatedItems` resultante contiene cinco entradas, el siguiente orden: `Chisel`, `Hammer`, `Nails`, `Screwdriver` y `Hacksaw`.

### Cómo evitar sobrescribir un atributo existente
<a name="Expressions.UpdateExpressions.SET.PreventingAttributeOverwrites"></a>

**Example**  
Establezca el valor de `Price` de un elemento, pero solo si este no tiene ya un atributo `Price`. (Si `Price` ya existe, no sucede nada).  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET Price = if_not_exists(Price, :p)" \
    --expression-attribute-values '{":p": {"N": "100"}}' \
    --return-values ALL_NEW
```

## REMOVE: eliminación de atributos de un elemento
<a name="Expressions.UpdateExpressions.REMOVE"></a>

Utilice la acción `REMOVE` en una expresión de actualización para eliminar uno o varios atributos de un elemento en Amazon DynamoDB. Para llevar a cabo varias acciones `REMOVE`, debe separarlas por comas.

A continuación se muestra un resumen de la sintaxis de `REMOVE` en una expresión de actualización. El único operando es la ruta de documento del atributo que se desea eliminar.

```
remove-action ::=
    path
```

**Example**  
Elimine algunos atributos de un elemento. (Si el atributo no existe, no sucede nada).  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "REMOVE Brand, InStock, QuantityOnHand" \
    --return-values ALL_NEW
```

### Eliminación de elementos de una lista
<a name="Expressions.UpdateExpressions.REMOVE.RemovingListElements"></a>

Puede utilizar `REMOVE` para eliminar entradas individuales de una lista.

**Example**  
En [Adición de elementos a una lista](#Expressions.UpdateExpressions.SET.UpdatingListElements), ha modificado un atributo de lista (`RelatedItems`) para que contenga cinco componentes:   
+ `[0]`—`Chisel`
+ `[1]`—`Hammer`
+ `[2]`—`Nails`
+ `[3]`—`Screwdriver`
+ `[4]`—`Hacksaw`
En el siguiente ejemplo de la AWS Command Line Interface (AWS CLI) se eliminan `Hammer` y `Nails` de la lista.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "REMOVE RelatedItems[1], RelatedItems[2]" \
    --return-values ALL_NEW
```
Después de eliminar `Hammer` y `Nails`, los componentes restantes se reordenan. Ahora, la lista contiene lo siguiente:  
+ `[0]`—`Chisel`
+ `[1]`—`Screwdriver`
+ `[2]`—`Hacksaw`

## ADD: actualización de números y conjuntos
<a name="Expressions.UpdateExpressions.ADD"></a>

**nota**  
En general, recomendamos usar `SET` en lugar de `ADD` para garantizar operaciones idempotentes.

Utilice la acción `ADD` en una expresión de actualización para agregar un nuevo atributo y sus valores a un elemento.

Si el atributo ya existe, el comportamiento de `ADD` depende del tipo de datos del atributo:
+ Si el atributo es un número y el valor que se agrega también es un número, entonces el valor se suma matemáticamente al atributo existente. (Si el valor es un número negativo, entonces se resta del atributo existente).
+ Si el atributo es un conjunto y el valor que se agrega también es un conjunto, entonces el valor se agrega al conjunto existente.

**nota**  
La acción `ADD` solo es compatible con los tipos de datos Number y Set.

Para llevar a cabo varias acciones `ADD`, debe separarlas por comas.

En el resumen de sintaxis siguiente:
+ El componente *path* es la ruta de documento de un atributo. El tipo de datos del atributo debe ser `Number` o Set. 
+ El componente *value* es un número que se desea agregar al atributo (si el tipo de datos es `Number`) o un conjunto que se desea agregar al atributo (si el tipo de datos es Set).

```
add-action ::=
    path value
```

En los temas siguientes se describen algunos casos de uso diferentes de la acción `ADD`.

**Topics**
+ [Adición de un número](#Expressions.UpdateExpressions.ADD.Number)
+ [Adición de elementos a un conjunto](#Expressions.UpdateExpressions.ADD.Set)

### Adición de un número
<a name="Expressions.UpdateExpressions.ADD.Number"></a>

Supongamos que el atributo `QuantityOnHand` no existe. En el siguiente ejemplo de la AWS CLI, `QuantityOnHand` se establece en 5.

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "ADD QuantityOnHand :q" \
    --expression-attribute-values '{":q": {"N": "5"}}' \
    --return-values ALL_NEW
```

Ahora que `QuantityOnHand` ya existe, puede volver a ejecutar el ejemplo para incrementar `QuantityOnHand` en 5 cada vez.

### Adición de elementos a un conjunto
<a name="Expressions.UpdateExpressions.ADD.Set"></a>

Supongamos que el atributo `Color` no existe. En el siguiente ejemplo de la AWS CLI, `Color` se establece en un conjunto de cadenas que contiene dos componentes.

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "ADD Color :c" \
    --expression-attribute-values '{":c": {"SS":["Orange", "Purple"]}}' \
    --return-values ALL_NEW
```

Ahora que `Color` ya existe, podemos agregarle más componentes.

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "ADD Color :c" \
    --expression-attribute-values '{":c": {"SS":["Yellow", "Green", "Blue"]}}' \
    --return-values ALL_NEW
```

## DELETE: eliminación de elementos de un conjunto
<a name="Expressions.UpdateExpressions.DELETE"></a>

**importante**  
La acción `DELETE` solo es compatible con tipos de datos `Set`.

Utilice la acción `DELETE` en una expresión de actualización para eliminar una o varias entradas de un conjunto. Para llevar a cabo varias acciones `DELETE`, debe separarlas por comas.

En el resumen de sintaxis siguiente:
+ El componente *path* es la ruta de documento de un atributo. El tipo de datos del atributo debe ser Set.
+ *Subset* representa uno o varios componentes que se van a eliminar de *path*. Para *subset* debe especificar un tipo de datos Set.

```
delete-action ::=
    path subset
```

**Example**  
En [Adición de elementos a un conjunto](#Expressions.UpdateExpressions.ADD.Set), crea el conjunto de cadenas `Color`. En este ejemplo se eliminan algunos de los componentes de ese conjunto.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "DELETE Color :p" \
    --expression-attribute-values '{":p": {"SS": ["Yellow", "Purple"]}}' \
    --return-values ALL_NEW
```

## Uso de varias expresiones de actualización
<a name="Expressions.UpdateExpressions.Multiple"></a>

Puede utilizar varias acciones en una sola expresión de actualización. Todas las referencias de atributos se resuelven en función del estado del elemento antes de aplicar cualquiera de las acciones.

**Example**  
Dado un elemento `{"id": "1", "a": 1, "b": 2, "c": 3}`, la siguiente expresión elimina `a` y desplaza los valores de `b` y `c`:  

```
aws dynamodb update-item \
    --table-name test \
    --key '{"id":{"S":"1"}}' \
    --update-expression "REMOVE a SET b = a, c = b" \
    --return-values ALL_NEW
```
El resultado es `{"id": "1", "b": 1, "c": 2}`. Aunque `a` se elimina y `b` se reasigna en la misma expresión, ambas referencias se resuelven con sus valores originales.

**Example**  
Si desea modificar el valor de un atributo y eliminar por completo otro, podría utilizar una acción SET y otra REMOVE en una sola instrucción. Esta operación reduciría el valor de `Price` a 15 a la vez que eliminaría el atributo `InStock` del elemento.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET Price = Price - :p REMOVE InStock" \
    --expression-attribute-values '{":p": {"N":"15"}}' \
    --return-values ALL_NEW
```

**Example**  
Si desea agregar un elemento a una lista al mismo tiempo que cambia el valor de otro atributo, podría utilizar dos acciones SET en una sola instrucción. Esta operación agregaría "Nails" al atributo de la lista `RelatedItems` y también establecería el valor de `Price` a 21.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET RelatedItems[1] = :newValue, Price = :newPrice" \
    --expression-attribute-values '{":newValue": {"S":"Nails"}, ":newPrice": {"N":"21"}}'  \
    --return-values ALL_NEW
```