Skip to content

Capítulo 4: Serviços Auxiliares e Persistência de Dados

4.2 Persistência de dados com o Oracle NoSQL

4.2.1 SQL vs. NoSQL

O principal propósito de um banco de dados é armazenar, gerenciar e recuperar grandes volumes de dados de forma eficiente e segura.

No modelo relacional, os dados são organizados em tabelas, onde cada tabela é composta por linhas e colunas. Essas tabelas podem se relacionar umas com as outras, formando relações que constituem a base do modelo relacional. É por essa razão que os bancos de dados que implementam esse modelo são conhecidos como Sistemas de Gerenciamento de Banco de Dados Relacional (SGBD) ou, em inglês, Relational Database Management System (RDBMS).

alt_text

Bancos de dados relacionais, como Oracle Database, MySQL e PostgreSQL, desempenham um papel vital na persistência segura das informações, além de gerenciar múltiplos acessos de escrita concorrente por meio de transações.

O termo "transação" refere-se a transações ACID (Atômicas, Consistentes, Isoladas e Duráveis), que asseguram a consistência dos dados, permitindo a adição, exclusão ou modificação de múltiplos registros em diferentes tabelas por meio de uma única operação. As transações incorporam o conceito de unidade de trabalho, garantindo sucesso total ou falha total (tudo ou nada), sem espaço para um meio termo. Além disso, as transações permitem decidir se as alterações devem ser persistidas (commit) ou descartadas (rollback).

Já os bancos de dados do tipo NoSQL, representam uma nova abordagem para o armazenamento e gerenciamento de dados, diferente do modelo relacional. Eles foram desenvolvidos para operar em grandes clusters de computadores, que favorecem a escalabilidade horizontal, e para atender à necessidade de aplicações que exigem um modelo de dados mais flexível ou schemaless.

NoSQL ("Not SQL" ou "Not Only SQL") não possui uma definição precisa. Ele é utilizado para descrever vários bancos de dados não relacionais, como Redis, MongoDB, Oracle NoSQL Database, Neo4J, entre outros.

Diferente dos bancos de dados do tipo NoSQL, bancos de dados relacionais não conseguem escalar horizontalmente devido ao funcionamento das transações ACID, que são incompatíveis com a execução em clusters de computadores. Isso ocorre porque não é possível garantir a consistência dos dados nem realizar um JOIN sobre dados distribuídos entre várias máquinas do cluster.

Para exemplificar, imagine uma instrução SQL que realiza um JOIN entre diferentes tabelas armazenadas em várias máquinas conectadas à rede (clusters de computadores). Esse JOIN, que precisa recuperar dados de diferentes tabelas pela rede, pode enfrentar problemas como alta latência ou até mesmo erros de conexão, resultando na impossibilidade de retornar os dados solicitados.

alt_text

Por outro lado, os bancos de dados relacionais foram projetados para operar em uma única máquina. Isso permite que as transações ACID sejam viáveis, uma vez que as tabelas estão contidas em uma única camada de storage, que pode ser dividida entre múltiplos discos conectados por barramentos de alta velocidade.

alt_text

É importante mencionar que os bancos de dados NoSQL não substituem os bancos de dados relacionais, e vice-versa. Os bancos de dados NoSQL, que lidam com dados não estruturados, complementam os bancos de dados SQL em soluções empresariais. Na prática, é fundamental entender as necessidades do negócio e identificar onde cada tecnologia se "encaixa melhor".

Resumo das principais diferenças

alt_text

4.2.2 Tipos de Banco de Dados NoSQL

A maioria dos bancos de dados NoSQL é baseada em alguma forma de estrutura chave/valor, sendo as quatro principais categorias as seguintes:

alt_text

  • Chave/Valor

    • Os dados são armazenados por meio de chaves únicas.
    • Aqui, o banco de dados não conhece nem se preocupa com o valor ao qual a chave se refere. Assim, a recuperação de dados só é possível por meio de consultas que envolvam as chaves.
  • Documentos

    • É bastante similar à implementação chave/valor e neste caso, o banco de dados conhece o valor (documento) ao qual a chave se refere.
  • Grafos

    • Semelhante ao modelo relacional.
    • É especialmente útil para dados altamente interconectados, uma vez que a estrutura de um grafo revela de forma natural os relacionamentos entre os objetos.
  • Colunar

    • O armazenamento colunar é semelhante a uma tabela.

4.2.3 Introdução ao Oracle NoSQL Database Cloud Service

O Oracle NoSQL Database Cloud Service é um serviço de banco de dados NoSQL totalmente gerenciado no OCI, que permite aos desenvolvedores concentrar-se no desenvolvimento de aplicações, em vez de se preocupar com a configuração de servidores.

O serviço oferece suporte ao armazenamento de documentos JSON, dados do tipo chave/valor e dados em colunas. Ele já inclui, por padrão, monitoramento, alta disponibilidade com dados distribuídos automaticamente entre Fault Domains e Availability Domains, além de fácil escalabilidade com baixo tempo de resposta. Além disso, fornece uma variedade de recursos adicionais, incluindo:

  • Suporte a transações ACID.
  • Atualizações parciais em documentos JSON.
  • Criação de índices adicionais.
  • Manipulação e acesso aos dados via linguagem SQL padrão.
  • TTL (Tempo de Vida) permite definir um tempo de expiração para as linhas da tabela, de modo que, ao ultrapassar esse limite, a linha será automaticamente excluída.
  • Replicação de dados entre diferentes regiões por meio da funcionalidade Global Active Tables.

NOTA

Para mais informações sobre o serviço, consulte o link "Oracle NoSQL Database Cloud Service".

Tabelas

No Oracle NoSQL, os dados são armazenados e organizados em Tabelas, sendo possível criar tanto tabelas sem um esquema fixo quanto tabelas com esquema fixo.

Uma tabela sem esquema, ou schemaless, é basicamente uma tabela que armazena documentos JSON, onde cada documento inserido pode ter uma estrutura única e independente. Nesse caso, o banco de dados não valida a estrutura interna do JSON antes de persistir os dados, ele apenas verifica se o dado possui um documento JSON válido.

1
2
3
4
CREATE TABLE IF NOT EXISTS produtos (
    id INTEGER GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1),
    propriedades JSON,
PRIMARY KEY(id))

Uma tabela com um esquema fixo possui colunas que têm tipos de dados específicos. Isso significa que, antes de persistir os dados, o banco de dados valida os dados em relação ao tipo definido para cada coluna. Por exemplo, uma coluna definida para armazenar valores inteiros aceitará apenas números inteiros, enquanto uma coluna de texto permitirá apenas strings.

1
2
3
4
5
6
7
8
CREATE TABLE IF NOT EXISTS produtos (
    id INTEGER GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1),
    nome STRING,
    descricao STRING,
    valor NUMBER NOT NULL DEFAULT 0,
    frete_gratis BOOLEAN DEFAULT TRUE,
    imagens ARRAY(STRING),
PRIMARY KEY(id))

NOTA

Consulte o link "Supported Data Types" para acessar a lista dos tipos de dados suportados pelo Oracle NoSQL.

O Oracle NoSQL também suporta tabelas híbridas (Hybrid Tables), que permitem a combinação de colunas do tipo JSON para armazenar documentos sem estrutura fixa e colunas com tipos de dados específicos.

1
2
3
4
5
6
7
CREATE TABLE IF NOT EXISTS produtos (
    id INTEGER GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1),
    propriedades JSON,
    valor NUMBER NOT NULL DEFAULT 0,
    frete_gratis BOOLEAN DEFAULT TRUE,
    imagens ARRAY(STRING),   
PRIMARY KEY(id))

alt_text

Independentemente de a tabela ter um esquema fixo ou não, é obrigatório criar pelo menos uma coluna destinada a ser a chave primária da tabela por meio da instrução PRIMARY KEY. As colunas designadas como chave primária devem ser dos tipos INTEGER, LONG, FLOAT, DOUBLE, NUMBER, STRING, ENUM, BOOLEAN ou TIMESTAMP.

A coluna id nas instruções SQL acima, além de ser a chave primária, é designada como coluna de identidade (IDENTITY Column). Essa coluna especial é projetada para gerar automaticamente valores únicos e sequenciais para cada novo registro inserido, eliminando a necessidade de gerenciar os valores da chave primária manualmente pela aplicação.

NOTA

Consulte o link "CREATE TABLE Statement" para obter mais informações sobre a sintaxe do comando CREATE TABLE, e "Using the IDENTITY Column" para saber mais sobre coluna de identidade no Oracle NoSQL.

Armazenamento, Unidades de Escrita e Leitura

Ao criar uma tabela, é necessário especificar a quantidade total de armazenamento em Gigabytes (maxStorageInGBs), além de duas propriedades que determinam as capacidades de leitura (maxReadUnits) e escrita (maxWriteUnits) da tabela, as quais são:

  • Unidades de Escrita ou Gravação (maxWriteUnits)

    • Uma unidade de escrita corresponde a um throughput de até 1 kilobyte (KB) de dados por segundo para operações como inserção, atualização ou exclusão de um registro. Atualizações de índices também consomem unidades de escrita.
    • Por exemplo: um registro com menos de 1 KB requer 1 unidade de escrita. Para operações em registros de 1,5 KB, são necessárias 2 unidades de escrita.
  • Unidades de Leitura (maxReadUnits)

    • Uma unidade de leitura corresponde a um throughput de até 1 kilobyte (KB) de dados por segundo em operações de leitura eventualmente consistentes.
    • Por exemplo, um registro com menos de 1 KB de dados exige apenas 1 unidade de leitura eventualmente consistente. Para um registro que contém 1,5 KB de dados, serão necessárias 2 unidades de leitura eventualmente consistentes.
  • Capacidade de Armazenamento em Gigabytes (maxStorageInGBs)

    • A capacidade de armazenamento refere-se ao total disponível em gigabytes (GB) para a tabela de dados NoSQL, representando a quantidade máxima de informações que podem ser armazenadas.

Durante a criação da tabela, tanto a capacidade de armazenamento quanto as unidades de leitura e escrita são controladas pelo parâmetro capacityMode, que pode ser definido manualmente (PROVISIONED) ou, deixar o OCI ajustar automaticamente os valores conforme a demanda por algum deles aumentar mais do que o especificado (ON_DEMAND).

Utilizar PROVISIONED é financeiramente mais barato, porém exige que o administrador ou alguma funcionalidade da aplicação, ajuste os valores para cima quando a demanda aumenta.

Por exemplo, no modo PROVISIONED, se a quantidade de leituras realizadas exceder o limite definido por maxReadUnits, uma exceção será retornada com a seguinte mensagem: Operation failed with limit exception: Read throughput rate exceeded for table user. Limit: 1 Units/Sec

Em contrapartida, ON_DEMAND é mais custoso, pois o OCI ajustará esses valores automaticamente, sem necessidade de intervenção.

Abaixo está um exemplo da criação de uma tabela em que seus limites de utilização são especificados pelo parâmetro --table-limits:

$ oci nosql table create \
> --region "sa-saopaulo-1" \
> --compartment-id "ocid1.compartment.oc1..aaaaaaaaaaaaaaaabbbbbbbbccc" \
> --name "pizza" \
> --table-limits "{\"capacityMode\": \"PROVISIONED\", \"maxReadUnits\": 5, \"maxWriteUnits\": 5, \"maxStorageInGBs\": 2}" \
> --wait-for-state "SUCCEEDED" \
> --ddl-statement "
     CREATE TABLE IF NOT EXISTS pizza (
        id INTEGER,
        name STRING,
        description STRING,
        image STRING,
        price NUMBER
     PRIMARY KEY(id))"

Para atualizar manualmente as capacidades da tabela, seja aumentando ou diminuindo, utilize o seguinte comando:

1
2
3
4
5
6
7
$ oci nosql table update \
> --region "sa-saopaulo-1" \
> --compartment-id "ocid1.compartment.oc1..aaaaaaaaaaaaaaaabbbbbbbbccc" \
> --table-name-or-id "pizza" \
> --table-limits "{\"capacityMode\": \"PROVISIONED\", \"maxReadUnits\": 15,\"maxWriteUnits\": 5, \"maxStorageInGBs\": 2}" \
> --wait-for-state "SUCCEEDED" \
> --force

NOTA

Para configurar o capacityMode como ON_DEMAND, os parâmetros maxReadUnits e maxWriteUnits devem ser definidos como zero (0), enquanto o parâmetro maxStorageInGBs deve ter um valor inicial superior a zero.

Leitura Eventual ou Absoluta

Ao lidar com dados distribuídos, como em bancos de dados do tipo NoSQL, outros dois conceitos se tornam fundamentais durante o processo de leitura dos dados que são:

  • Consistência de Leitura Eventual

    • Isso indica que os dados retornados de uma operação de leitura podem não ser os mais recentemente gravados.
    • Para uma melhor compreensão, imagine que uma operação de escrita foi recentemente executada (inserção, atualização ou exclusão). Os dados dessa operação precisam ser replicados em todos os nós do cluster para garantir a consistência das informações. O tempo necessário para essa replicação pode impactar a consistência das leituras e, dependendo das exigências do seu negócio, essa latência pode ser aceitável e é denominada consistência eventual ou eventualmente consistente.
  • Consistência de Leitura Absoluta

    • Os dados retornados a partir de uma operação de leitura, são os mais recentes gravados.
    • Nesse caso, uma operação de leitura é realizada em vários nós do cluster para comparar a consistência dos dados e retornar o registro mais recentemente gravado.

Por meio das APIs do Oracle NoSQL é possível especificar o tipo de leitura desejada, seja ela Eventual (EVENTUAL) ou Absoluta (ABSOLUTE).

Por exemplo, o comando abaixo realiza uma Leitura Absoluta através do parâmetro --consistency "ABSOLUTE":

$ oci nosql query execute \
> --region "sa-saopaulo-1" \
> --compartment-id "ocid1.compartment.oc1..aaaaaaaaaaaaaaaabbbbbbbbccc" \
> --consistency "ABSOLUTE" \
> --statement "SELECT name, email, telephone FROM user WHERE email='rita.cassia@ocipizza.com.br'"
{
  "data": {
    "items": [
      {
        "email": "rita.cassia@ocipizza.com.br",
        "name": "Rita de Cássia",
        "telephone": "16999999999"
      }
    ],
    "usage": {
      "read-units-consumed": 20,
      "write-units-consumed": 0
    }
  }
}

Hierarquias de Tabelas

O Oracle NoSQL permite criar tabelas que seguem um relacionamento pai-filho. Isso é conhecido como Hierarquias de Tabelas.

Hierarquias de Tabelas são uma forma de estabelecer relações de dados do tipo 1 para N entre uma ou mais tabelas, funcionando de maneira semelhante às chaves estrangeiras (FOREIGN KEY) que conectam duas ou mais tabelas em bancos de dados relacionais.

Por exemplo, na aplicação OCI PIZZA, existe um relacionamento pai-filho entre a tabela user e a tabela order, formando assim a relação user.order.

alt_text

NOTA

O Oracle NoSQL utiliza a notação de ponto entre os nomes das tabelas para representar os relacionamentos entre elas.

A tabela filha, ou Child Table, herda as colunas da chave primária de sua tabela pai, além das propriedades relacionadas ao total de armazenamento, unidades de escrita e leitura.

Por exemplo, a seguinte instrução SELECT demonstra como um JOIN no Oracle NoSQL pode ser usado para recuperar todos os pedidos de pizzas feitos pela usuária "Rita de Cássia" na aplicação OCI PIZZA:

1
2
3
SELECT name, email, telephone, pizza FROM user User
    LEFT OUTER JOIN user.order UserOrder ON User.id=UserOrder.id
WHERE User.name="Rita de Cássia"

NOTA

Consulte o link "Overview of Left Outer Joins" para maiores informações sobre a instrução LEFT OUTER JOIN.

Global Active Tables

O Global Active Tables é uma funcionalidade do Oracle NoSQL que permite a replicação de dados de tabelas de forma transparente entre as regiões do OCI. Isso significa que os dados escritos ou atualizados em uma tabela em uma região específica, são automaticamente replicados para outras regiões que fazem parte do esquema de replicação.

Essa funcionalidade é útil, pois possibilita a execução simultânea de aplicações em diferentes regiões (modo ativo-ativo). Um exemplo disso é a aplicação OCI PIZZA, que opera simultaneamente nas regiões sa-saopaulo-1 e sa-vinhedo-1. Além disso, oferece tolerância a falhas em caso de indisponibilidade de uma região.

A seguir, estão algumas considerações importantes para ativar o Global Active Tables:

1. Freeze e Unfreeze

O esquema da tabela deve ser alterado de Mutável para Não Mutável (FREEZE) usando a instrução ALTER TABLE <tabela> FREEZE SCHEMA FORCE. Essa ação é necessária para evitar qualquer modificação no esquema da tabela replicada e pode ser executada com o seguinte comando:

1
2
3
4
5
6
7
$ oci nosql table update \
> --region "sa-saopaulo-1" \
> --table-name-or-id "pizza" \
> --compartment-id "ocid1.compartment.oc1..aaaaaaaaaaaaaaaabbbbbbbbccc" \
> --ddl-statement "ALTER TABLE pizza FREEZE SCHEMA FORCE" \
> --wait-for-state "SUCCEEDED" \
> --force

Após concluir o FREEZE do esquema, é possível configurar a replicação para a região desejada utilizando o seguinte comando:

1
2
3
4
5
6
$ oci nosql table create-replica \
> --region "sa-saopaulo-1" \
> --replica-region "sa-vinhedo-1" \
> --compartment-id "ocid1.compartment.oc1..aaaaaaaaaaaaaaaabbbbbbbbccc" \
> --table-name-or-id "pizza" \
> --wait-for-state "SUCCEEDED"

Se for necessário fazer qualquer alteração no esquema, é preciso primeiro remover a réplica e, em seguida, retornar o esquema para Mutável (UNFREEZE) usando a instrução ALTER TABLE <tabela> UNFREEZE SCHEMA.

Isso pode ser realizado usando a sequência de comandos a seguir:

1
2
3
4
5
6
7
$ oci nosql table delete-replica \
> --region "sa-saopaulo-1" \
> --replica-region "sa-vinhedo-1" \
> --compartment-id "ocid1.compartment.oc1..aaaaaaaaaaaaaaaabbbbbbbbccc" \
> --table-name-or-id "pizza" \
> --wait-for-state "SUCCEEDED" \
> --force
1
2
3
4
5
6
7
$ oci nosql table update \
> --region "sa-saopaulo-1" \
> --table-name-or-id "pizza" \
> --compartment-id "ocid1.compartment.oc1..aaaaaaaaaaaaaaaabbbbbbbbccc" \
> --ddl-statement "ALTER TABLE pizza UNFREEZE SCHEMA" \
> --wait-for-state "SUCCEEDED" \
> --force

NOTA

O script "nosql-replica.sh", que é responsável pela criação das réplicas e pelo FREEZE dos esquemas das tabelas da aplicação OCI PIZZA, está localizado no diretório "scripts/capitulo-4" do repositório de códigos.

2. Colunas de Identidade

Colunas de identidade (IDENTITY Column) não podem ser utilizadas, pois não é possível garantir a unicidade dos seus valores entre as regiões que participam do esquema de replicação. Nesse cenário, a responsabilidade pela unicidade dos valores recai sobre a aplicação.

3. Replicação Assíncrona

As atualizações das tabelas que participam do esquema de replicação são realizadas de forma assíncrona. Isso significa que, ao executar uma operação de escrita ou atualização de dados em uma região, essa ação é concluída primeiro nessa região, antes que os dados sejam replicados para as demais regiões.

4.2.4 Oracle NoSQL Database Python SDK

Existem duas formas para acessar e trabalhar com o Oracle NoSQL em uma aplicação Python:

OCI Python SDK

A forma mais simples de interagir com o Oracle NoSQL é através do OCI Python SDK. Nesse modo, o acesso ao serviço é realizado exclusivamente por meio das APIs REST do OCI. No entanto, essa abordagem não é a mais recomendada para manipular grandes volumes de dados que exigem a execução de consultas mais complexas.

import oci

COMPARTMENT_ID = 'ocid1.compartment.oc1..aaaaaaaaaaaaaaaabbbbbbbbccc'

config = oci.config.from_file()
nosql_client = oci.nosql.NosqlClient(config=config)

query_details = oci.nosql.models.QueryDetails(
    compartment_id=COMPARTMENT_ID,
    consistency='ABSOLUTE',
    statement='SELECT name, telephone FROM user WHERE id=1'
)

resp = nosql_client.query(query_details=query_details)

print(resp.data)

Consultas mais complexas, como por exemplo a instrução SELECT max(id) FROM user, não são suportadas, resultando em mensagens de exceção como: The driver or SDK being used does not support complex query.

Oracle NoSQL Database Python SDK (borneo)

O Borneo é um driver para o Oracle NoSQL que utiliza um protocolo binário e que pode ser utlizado para lidar com grandes volumes de dados além de possibilitar a execução de consultas complexas.

Além de ser a forma utilizada pela aplicação OCI PIZZA, é a opção mais recomendada para interagir com o Oracle NoSQL, tanto no OCI quanto em instalações on-premises.

Borneo requer o OCI Python SDK, e ambos podem ser instalados com o comando a seguir:

(venv) $ pip install oci borneo

A utilização do Borneo requer mais parametrizações no código em comparação ao OCI Python SDK.

Por exemplo, o código a seguir pode ser utilizado para executar a instrução SELECT max(id) FROM user:

from borneo.iam import SignatureProvider
from borneo import NoSQLHandleConfig, NoSQLHandle, Regions
from borneo import Consistency, QueryRequest

COMPARTMENT_ID = 'ocid1.compartment.oc1..aaaaaaaaaaaaaaaabbbbbbbbccc'

sigprov = SignatureProvider(config_file='~/.oci/config')

nosql_handle_config = NoSQLHandleConfig(Regions.SA_SAOPAULO_1)
nosql_handle_config.set_authorization_provider(sigprov)
nosql_handle_config.set_default_compartment(COMPARTMENT_ID)

nosql_handle = NoSQLHandle(nosql_handle_config)

query_request = QueryRequest()
query_request.set_consistency(Consistency.ABSOLUTE)        
query_request.set_statement('SELECT max(id) FROM user')

resp = nosql_handle.query(query_request)

nosql_handle.close()

print(resp.get_results())

NOTA

Embora os exemplos usem a linguagem de programação Python, o Oracle NoSQL SDK está disponível para várias outras linguagens de programação, como Java, Go, Node.js, entre outras. Para uma lista completa dos SDKs para as diferentes linguagens de programação suportadas, consulte o link "Getting started with Oracle NoSQL Database".

4.2.5 Escrita ou Atualização Condicional

Tanto o OCI Python SDK quanto o Borneo oferecem a funcionalidade de escrita e atualização condicional nos dados das tabelas.

A escrita ou atualização condicional permite, de maneira simples, inserir novos dados ou atualizar os existentes, sem a necessidade de utilizar instruções SQL, como INSERT ou UPDATE. Esse processo é controlado pelos seguintes parâmetros:

  • IF_ABSENT

    • Os novos valores serão inseridos somente se os dados não existirem.
  • IF_PRESENT

    • Os valores serão atualizados apenas se os dados já existirem.

IF_ABSENT e IF_PRESENT realizam verificações na chave primária da tabelas para determinar se um novo registro deve ser inserido ou se um registro existente deve ser atualizado.

Por exemplo, através do OCI Python SDK, o novo usuário de nome Giovanna Armbrust não será inserido na tabela users pelo fato da chave primária informada já existir (id=3):

#!/usr/bin/env python3

import oci

COMPARTMENT_ID = 'ocid1.compartment.oc1..aaaaaaaaaaaaaaaabbbbbbbbccc'

new_user_data = {
    'id': 3, 
    'name': 'Giovanna Armbrust', 
    'email': 'gi.armbrust@ocipizza.com.br',
    'telephone': '88777777777'
}

config = oci.config.from_file(file_location='~/.oci/config')
nosql_client = oci.nosql.NosqlClient(config=config)

update_row_details = oci.nosql.models.UpdateRowDetails(
    compartment_id=COMPARTMENT_ID,
    option='IF_ABSENT',
    value=new_user_data
)

nosql_client.update_row(
    table_name_or_id='user',
    update_row_details=update_row_details
)

Através do Oracle NoSQL Database Python SDK (borneo), o código ficaria:

#!/usr/bin/env python3

from borneo.iam import SignatureProvider
from borneo import NoSQLHandleConfig, NoSQLHandle, Regions
from borneo import PutRequest, PutOption

COMPARTMENT_ID = 'ocid1.compartment.oc1..aaaaaaaaaaaaaaaabbbbbbbbccc'

new_user_data = {
    'id': 3,
    'name': 'Giovanna Armbrust',
    'email': 'gi.armbrust@ocipizza.com.br',
    'telephone': '88777777777'
}

sigprov = SignatureProvider(config_file='~/.oci/config')

nosql_handle_config = NoSQLHandleConfig(Regions.SA_SAOPAULO_1)
nosql_handle_config.set_authorization_provider(sigprov)
nosql_handle_config.set_default_compartment(COMPARTMENT_ID)

nosql_handle = NoSQLHandle(nosql_handle_config)

put_request = PutRequest()
put_request.set_option(PutOption.IF_ABSENT)
put_request.set_table_name('user')
put_request.set_value(new_user_data)
put_request.set_return_row(True)

nosql_handle.put(put_request)

nosql_handle.close()

NOTA

Os códigos apresentados nos exemplos acima podem ser encontrados no diretório "scripts/capitulo-4" do repositório de códigos da aplicação OCI PIZZA, com os seguintes nomes: "nosql-oci-sdk-absent.py" e "nosql-borneo-absent.py".

4.2.6 Tabelas da Aplicação OCI PIZZA

A aplicação OCI PIZZA utiliza quatro tabelas do serviço Oracle NoSQL, cujos dados são replicados entre as regiões sa-saopaulo-1 e sa-vinhedo-1 através da funcionalidade Global Active Tables.

Abaixo, segue uma descrição de cada uma das tabelas:

  • pizza

    • Tabela que armazena informações sobre o cardápio de pizzas, incluindo o nome da pizza, uma descrição e o nome do arquivo correspondente à imagem da pizza.
    • O nome do arquivo da imagem corresponde ao arquivo que foi transferido para o Object Storage.
  • user

    • Tabela que armazena os usuários da aplicação, incluindo nome, e-mail, senha, telefone e o status de confirmação do cadastro, indicando se o usuário validou seu registro.
    • Cada novo usuário recebe um e-mail com um link para confirmar seu cadastro após a inscrição.
  • user.order

    • A tabela order é filha da tabela user e é utilizada para registrar os pedidos de pizzas feitos pelos usuários (ordens de compra).
  • email_verification

    • Tabela de dados temporários utilizada para confirmar o cadastro de novos usuários e para o processo de redefinição de senha.
    • Cada novo usuário recebe um e-mail com um link que contém um token temporário, utilizado para ativar o cadastro. O processo de redefinição de senha segue a mesma lógica.
    • Essa tabela também utiliza a funcionalidade que remove automaticamente registros com mais de um dia de idade (TTL 1 DAYS). Assim, qualquer registro que ultrapassar um dia, será automaticamente excluído pelo serviço.

Criação, Réplica e Dados

No diretório "scripts/capitulo-4" do repositório de códigos da aplicação OCI PIZZA, você encontrará alguns scripts e um diretório de dados que servem para criar as tabelas da aplicação e ativar suas réplicas na região sa-vinhedo-1.

Abaixo está a descrição de cada um deles:

  • data/

    • Diretório que contém os arquivos pizza.data, user.data e order.data. Esses arquivos contêm um conjunto de dados utilizados para popular as tabelas da aplicação.
  • nosql-tables.sh

    • Script utilizado para criar as tabelas da aplicação no compartimento cmp-database do ambiente de produção na região sa-saopaulo-1.
  • nosql-replica.sh

    • Script utilizado para criar as réplicas das tabelas na região sa-vinhedo-1. É importante notar que as tabelas nessa região serão criadas automaticamente assim que a réplica for ativada, não sendo necessário criá-las antes da ativação.
  • nosql-data.sh

    • Script utilizado para popular as tabelas da aplicação com os arquivos de dados disponíveis no diretório data/.

Por fim, esses scripts devem ser executados na seguinte ordem:

  1. nosql-tables.sh
  2. nosql-replica.sh
  3. nosql-data.sh