Criando um CRUD básico em python com DynamoDB

Resumo: Este tutorial mostra como fazer um CRUD básico no DynamoDB, que é um banco de dados NoSQL da AWS, utilizando a linguagem Python. Para isso será mostrado primeiro como fazer o download da versão local do DynamoDB (que é usada para testes) e como configurar esta versão localmente. No final será mostrado como mudar as configurações para usar o DynamoDB na nuvem da AWS.
Requisitos: Conhecimento intermediário na linguagem Python.

O tutorial é dividido em 6 passos:
Passo 1 – Baixar o DynamoDB local
Passo 2 – Baixar e configurar AWS CLI
Passo 3 – Configurar e rodar o DynamoDB localmente
Passo 4 – Instalar Boto3
Passo 5 – Operações no DynamoDB: Criação da tabela, Inserção de item, Consulta de item, Atualização de item e Exclusão de item
Passo 6 – Como configurar web service

Passo 1 – Baixar o DynamoDB local

Antes de tudo, devemos baixar o DynamoDB para usá-lo localmente no nosso computador. Você pode ir no link Deploying DynamoDB Locally on Your Computer – Amazon DynamoDB e seguir o passo a passo da própria documentação da Amazon. Porém aqui vai um resumo: primeiro baixe o arquivo que se encontra no link acima, depois extraia para uma pasta de seu computador de sua preferência desejo.

Passo 2 – Baixar e configurar AWS CLI

Para configurar os serviços da AWS, você vai precisar ter o AWS Command Line Interface (AWS CLI) instalado e configurado corretamente em seu computador. O artigo a seguir explica como fazer isso: Installing, updating, and uninstalling the AWS CLI version 2 – AWS Command Line Interface.

Passo 3 – Configurar e rodar o DynamoDB localmente

Depois dos dois primeiros passos, precisamos rodar o DynamoDB localmente. Para isso utilizamos o comando:

java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -sharedDb
  • Observação 1: esse comando precisa ser executado na pasta selecionada no Passo 1.
  • Observação 2: o comando a ser executado no Windows via Windows PowerShell é:
java -D"java.library.path=./DynamoDBLocal_lib" -jar DynamoDBLocal.jar
  • Observação 3: a opção -sharedDb é utilizada para criar um único arquivo de banco de dados nomeado shared-local-instance.db que será utilizado por todos os programas que se conectarem ao DynamoDB. Se essa opção for omitida, o arquivo será nomeado com a ID de chave de acesso e região da AWS da forma que são exibidos na configuração do aplicativo. Seja qual for a opção escolhida, se você excluir esses arquivos perderá tudo que está armazenado neles.

Depois disso o DynamoDB estará rodando na porta 8000 do seu PC. Para parar é só apertar as teclas Ctrl e c.

Imagem da execução e configuração do DynamoDB local

Passo 4 – Instalar Boto3

O quarto passo é instalar a biblioteca boto3 que dá acesso aos serviços da AWS na linguagem Python. Para isso usaremos o pip com o seguinte comando:

pip install boto3

Uma mensagem como a da imagem abaixo deverá aparecer no terminal utilizado:

Mensagem da instalação do boto3 com sucesso

Passo 5 – Operações no DynamoDB

Nesse tutorial iremos simular um banco de dados que contenha informações de usuários, cada usuário terá um nome e uma profissão obrigatoriamente.

O trecho de código abaixo se repetirá várias vezes ao longo deste tutorial, por isso é importante compreendê-lo logo. Aqui especificamos o recurso como sendo o DynamoDB e passamos o local onde esse DynamoDB irá rodar, no caso o localhost 8000. Essa é a configuração básica do DynamoDB utilizando a biblioteca boto3. No último passo desse tutorial aprenderemos como trocar essa configuração para usar o DynamoDB como web service.

if not dynamodb:
    dynamodb = boto3.resource(
        'dynamodb', endpoint_url="http://localhost:8000")

Criação da tabela

Depois disso nós criamos a tabela usando a função create_table do DynamoDB. O atributo name será a partition key, enquanto o atributo occupation será a sort key.

  • Partition key: é a chave primária da tabela. Internamente o DynamoDB usa uma função hash nesse atributo para decidir onde o item vai ser armazenado.
  • Partition key + sort key: basicamente é uma chave primária composta. Vários itens podem ter a mesma partition key e devido a isso serão armazenados juntos, em ordem (aqui é onde entra a sort key). Cada um desses itens deverá ter uma sort key única.

Na parte da criação também são indicados os tipos de cada atributo, como também a capacidade de leitura e escrita da tabela (que é ignorada no DynamoDB local) através do ProvisionedThroughput.

import boto3

def create_users_table(dynamodb=None):
    if not dynamodb:
        dynamodb = boto3.resource(
            'dynamodb', endpoint_url="http://localhost:8000")

    table = dynamodb.create_table(
        TableName='Users',
        KeySchema=[
            {
                'AttributeName': 'name',
                'KeyType': 'HASH'  # Partition key
            },
            {
                'AttributeName': 'occupation',
                'KeyType': 'RANGE'  # Sort key
            }
        ],
        AttributeDefinitions=[
            {
                'AttributeName': 'name',
                'AttributeType': 'S'
            },
            {
                'AttributeName': 'occupation',
                'AttributeType': 'S'
            },

        ],
        ProvisionedThroughput={
            'ReadCapacityUnits': 1,
            'WriteCapacityUnits': 1
        }
    )
    return table

if __name__ == '__main__':
    users_table = create_users_table()
    print("Table status:", users_table.table_status)

Inserção de item na tabela

No código abaixo inserimos um usuário na tabela, também através da função put_item e mostramos o resultado da inserção. É bom lembrar que tanto o atributo name quanto o atributo occupation são obrigatórios já que são a partition key e a sort key respectivamente.Veja também como a partir daqui sempre precisaremos “pegar” a tabela através do dynamodb.Table(). Dentro dos parênteses você deve sempre passar o nome da tabela na qual quer fazer as alterações.

import boto3
from pprint import pprint

def put_user(name, occupation, hobby, dynamodb=None):
    if not dynamodb:
        dynamodb = boto3.resource(
            'dynamodb', endpoint_url="http://localhost:8000")

    table = dynamodb.Table('Users')
    response = table.put_item(
        Item={
            'name': name,
            'occupation': occupation,
            'hobby': hobby
        }
    )
    return response

if __name__ == '__main__':
    user_resp = put_user("Thamires", "Student", "games")
    print("Put user succeeded:")
    pprint(user_resp, sort_dicts=False)

Já no código abaixo fazemos uma inserção de alguns usuários na tabela. Esse tipo de função pode ser utilizada para ler vários itens vindos de um arquivo JSON por exemplo (que no código é representado pela lista de dicionários python users_list).

import boto3

def load_users(users, dynamodb=None):
    if not dynamodb:
        dynamodb = boto3.resource(
            'dynamodb', endpoint_url="http://localhost:8000")

    table = dynamodb.Table('Users')
    for user in users:

        name = str(user['name'])
        occupation = str(user['occupation'])
        print("Adding user:", name, occupation)
        table.put_item(Item=user)

if __name__ == '__main__':
    user1 = {
        "name": "Paulo",
        "occupation": "Teacher"
    }
    user2 = {
        "name": "Ana",
        "occupation": "Mobile developer"
    }
    users_list = [user1, user2]
    load_users(users_list)

Consulta de item na tabela

Abaixo está uma função get_user simples. Usamos a função get_item passando a partition key e a sort key do item para pegar determinado item da tabela. No fim, nós imprimimos esse item na tela.

import boto3
from botocore.exceptions import ClientError
from pprint import pprint

def get_user(name, occupation, dynamodb=None):
    if not dynamodb:
        dynamodb = boto3.resource(
            'dynamodb', endpoint_url="http://localhost:8000")

    table = dynamodb.Table('Users')

    try:
        response = table.get_item(Key={'name': name, 'occupation': occupation})
    except ClientError as e:
        print(e.response['Error']['Message'])
    else:
        return response['Item']

if __name__ == '__main__':
    user = get_user("Thamires", "Student")
    if user:
        print("Get user succeeded:")
        pprint(user, sort_dicts=False)

Atualização de item na tabela

Na função update_user, atualizamos um determinado item já contido na tabela. Para isso passamos a key dele (partition e sort key) na função update_item. Também informamos o que seria atualizado nesse item através da UpdateExpression, como também informamos os valores que seriam usados nessa expressão através da ExpressionAttributeValues.

Perceba que quando chamamos a função update_user passamos a chave primária composta por meio dos parâmetros, como também um hobby – que é o atributo, que ainda não existe nesse item, que vai ser adicionado a ele.

from decimal import Decimal
from pprint import pprint
import boto3

def update_user(name, occupation, hobby, dynamodb=None):
    if not dynamodb:
        dynamodb = boto3.resource(
            'dynamodb', endpoint_url="http://localhost:8000")

    table = dynamodb.Table('Users')

    response = table.update_item(
        Key={
            'name': name,
            'occupation': occupation
        },
        UpdateExpression="set hobby=:h",
        ExpressionAttributeValues={
            ':h': hobby
        },
        ReturnValues="UPDATED_NEW"
    )
    return response

if __name__ == '__main__':
    update_response = update_user("Thamires", "Student", "Read books")
    print("Update user succeeded:")
    pprint(update_response, sort_dicts=False)

Exclusão de item na tabela

Como nas funções anteriores, também utilizamos a chave composta para deletar um item da tabela Users no DynamoDB. Usamos a função delete_item na tabela e passamos a chave.

from pprint import pprint
import boto3
from botocore.exceptions import ClientError

def delete_user(name, occupation, dynamodb=None):
    if not dynamodb:
        dynamodb = boto3.resource(
            'dynamodb', endpoint_url="http://localhost:8000")

    table = dynamodb.Table('Users')

    try:
        response = table.delete_item(
            Key={
                'name': name,
                'occupation': occupation
            }
        )
    except ClientError as e:
        print(e.response['Error']['Message'])
    else:
        return response

if __name__ == '__main__':
    delete_response = delete_user("Thamires", "Student")
    if delete_response:
        print("Delete user succeeded:")
        pprint(delete_response, sort_dicts=False)

Passo 6 – Como configurar web service

Para utilizar o DynamoDB como web service uma simples alteração precisa ser feita nos códigos mostrados no decorrer desse tutorial. Na configuração do DynamoDB utilizando o boto3, você trocará o segundo parâmetro que antes era endpoint_url para region_name e passará a região que deseja utilizar. A partir daí, sempre que rodar o código as alterações não mais serão feitas localmente e sim na região escolhida por você.

    if not dynamodb:
        dynamodb = boto3.resource(
            'dynamodb', region_name="us-east-1")

Abaixo se encontra uma imagem do console da AWS após o código de criação de tabela ser rodado com as substituições feitas acima.

Referências

  1. Banco de dados NoSQl – Amazon Web Services 
  2. Installing, updating, and uninstalling the AWS CLI version 2 – AWS Command Line Interface 
  3. Quickstart — Boto3 Docs 1.16.44 documentation
  4. Deploying DynamoDB Locally on Your Computer – Amazon DynamoDB
  5. Getting Started Developing with Python and DynamoDB – Amazon DynamoDB

Este material foi produzido por Thamires Lopes como parte da avaliação da disciplina Projeto Interdisciplinar para Sistemas de Informação IV na UFRPE. Abaixo contato da autora.
github: github.com/Thamires-Lopes

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google

Você está comentando utilizando sua conta Google. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s