Crud DynamoDb
Tags: dynamodb, aws, boto3, python
Published: 2021-09-27 23:22:20

DynamoDb me parece una buena opción para utilizar una base de datos (no relacional) en la nube.

DynamoDb se puede utilizar en diferentes tamaños de proyectos desde proyectos pequeños a muy grandes, con todas son bondades de tiempos de respuesta bajos y gran escalabilidad.

## Ejercicio

Vamos a almacenar los resultados de los partidos de futbol de una o mas ligas.

**Requisitos:**

* Tener una cuenta de AWS
* Tener configuradas las credenciales de AWS en la maquina (en la consola de mac o linux ejecutar AWS configure para definir el Access key ID).Se utiliza este método solo por ser 'practico', no es aconsejable para entornos productivos.
* Tener instalado python y la libreria boto3 (pip install boto3)

**Editor**

Visual Studio Code


1) Inicialmente se debe importar la librería de boto3 e iniciar el recurso para la utilización de DynamoDB

```
import boto3
from boto3.dynamodb.conditions import Key
dynamodb = boto3.resource("dynamodb")


```
2) Creación de la tabla **PartidosFutbol** con la Partition Key **Liga** (tipo string) y la Sort Key **Partido** (tipo string)

```
dynamodb.create_table(
        TableName='PartidosFutbol',
        KeySchema=[
            {
                'AttributeName': 'Liga',
                'KeyType': 'HASH'  # Partition key
            },
            {
                'AttributeName': 'Partido',
                'KeyType': 'RANGE'  # Sort key
            }
        ],
        #Se deben crear las llaves nuevamente con su tipo de dato
        AttributeDefinitions=[
            {
                'AttributeName': 'Liga',
                'AttributeType': 'S'  # Se utiliza S para tipos de datos String y N para numeros
            },
            {
                'AttributeName': 'Partido',
                'AttributeType': 'S'
            }

        ],
        ProvisionedThroughput={
            'ReadCapacityUnits': 5,
            'WriteCapacityUnits': 5
        }
    )
```
3) Vamos a ingresar el resultado de un partido de futbol
Chelsea 1 - 2 Machester City de la Premier League, jugado el 26/09/2021

```
table = dynamodb.Table("PartidosFutbol")
table.put_item(Item={
    "Liga": "Premier League#2021/22",
    "Partido":"Chelsea#Manchester City#2021/09/26",
    "Local":"Chelsea",
    "Visitante":"Manchester City",
    "MarcadorLocal":1,
    "MarcadorVisitante": 2,
    "Fecha":"2021/09/26"

})
```
4) Revisando el resultado final no fue Chelsea 1 - 2 Manchester City, el resultado final fue: Chelsea 0 - 1 Manchester City. Por lo tanto debemos actualizar la información en nuestra base de datos.

```
table.update_item(
                Key={
                    "Liga": "Premier League#2021/22",
                    "Partido": "Chelsea#Manchester City#2021/09/26"
                },
                UpdateExpression="set MarcadorVisitante=:marcador_visitante,MarcadorLocal=:marcador_local",
                ExpressionAttributeValues={
                    ":marcador_visitante":1,
                    ":marcador_local":0
                },
                ReturnValues="UPDATED_NEW"
            )
```
Es importante tener en cuenta, para las actualizaciones se debe usar siempre el Partition Key y el Sort Key siempre y cuando este ultimo se haya definido en la tabla.

5) Como nuestra base de datos tiene muy poca información, vamos a registrar mas resultados.

```
partidos = []
partido1 = {"Liga": "Premier League#2021/22","Partido":"Arsenal#Tottenham Hotspur#2021/09/26","Local":"Arsenal","Visitante":"Tottenham","MarcadorLocal":3,"MarcadorVisitante": 1,"Fecha":"2021/09/25"}
partido2 = {"Liga": "LaLiga#2021/22","Partido":"Athletic Bilbao#Rayo Vallecano#2021/09/21","Local":"Athletic Bilbao","Visitante":"Rayo Vallecano","MarcadorLocal":1,"MarcadorVisitante": 2,"Fecha":"2021/09/21"}
partidos.append(partido1)
partidos.append(partido2)
with table.batch_writer() as batch:
    for p in partidos:
        content = {
            "Liga": p["Liga"],
            "Partido":p["Partido"],
            "Local":p["Local"],
            "Visitante":p["Visitante"],
            "MarcadorLocal":p["MarcadorLocal"],
            "MarcadorVisitante": p["MarcadorVisitante"],
            "Fecha":p["Fecha"]
        }
        batch.put_item(Item=content)
```
*batch_writer*: nos sirve para escribir o borrar muchos datos de manera eficiente.

6)Ahora vamos a consultar los partidos de la liga inglesa.

```
table.query(KeyConditionExpression=Key('Liga').eq("Premier League#2021/22"),                   
                        ProjectionExpression="table.query(KeyConditionExpression=Key('Liga').eq("Premier League#2021/22"),                   
                        ProjectionExpression="#L,MarcadorLocal,Visitante,MarcadorVisitante",
                        ExpressionAttributeNames = {'#L': 'Local'}
),MarcadorLocal,Visitante,MarcadorVisitante",
                        ExpressionAttributeNames = {'#L': 'Local'}
)
```
**ProjectionExpression**: Se utiliza para definir que columnas va a retornar la consulta
**ExpressionAttributeNames**: Se utiliza para definir los alias de las columnas

En este caso se utiliza el alias #L para la columna Local ya que *Local* es una palabra reservada de DynamoDB

7)Ahora queremos traer un partido especifico de la liga española.

```
table.query(KeyConditionExpression=Key('Liga').eq("LaLiga#2021/22") & Key("Partido").eq("Athletic Bilbao#Rayo Vallecano#2021/09/21")
)
```

8)En este paso vamos a traer los partido por una fecha especifica.

```
table.query(KeyConditionExpression=Key('Liga').eq("Premier League#2021/22"),                   
                        FilterExpression= 'Fecha = :Fecha',
                        ExpressionAttributeValues= { 
                        ':Fecha': '2021/09/25'
                        }
)
```
9)Como ultimo paso de nuestro **CRUD** vamos a eliminar un partido de nuestra tabla.

```
table.delete_item(
            Key={
                'Liga': "Premier League#2021/22",
                "Partido":"Chelsea#Manchester City#2021/09/26"
            },
            ConditionExpression="MarcadorLocal = :marcador_local and MarcadorVisitante =:marcador_visante",
            ExpressionAttributeValues={
                ":marcador_local": 0,
                ":marcador_visante": 1,
            }
        )

```
Para el caso de *delete_item* se debe especificar la Partition Key y el Sort Key siempre y cuando este ultimo se haya definido en la tabla.

# Referencias
[Boto3](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#DynamoDB.Client.create_table)
[Documentación DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GettingStarted.Python.01.html)

Me pueden encontrar en

[Camilo Cabrales](https://www.linkedin.com/in/camilo-cabrales-31a0bb53/)