Caso de uso de negócios do sistema de gerenciamento de reclamações
O DynamoDB é um banco de dados adequado para um caso de uso de sistema de gerenciamento de reclamações (ou central de atendimento), pois a maioria dos padrões de acesso associados a eles corresponde a pesquisas transacionais baseadas em chave-valor. Os padrões de acesso típicos nesse cenário seriam:
-
Criar e atualizar reclamações.
-
Escalar uma reclamação.
-
Criar e ler comentários sobre uma reclamação.
-
Receber todas as reclamações de um cliente.
-
Receber todos os comentários de um agente e receber todos os encaminhamentos.
Alguns comentários podem conter anexos que descrevem a reclamação ou a solução. Embora todos esses sejam padrões de acesso de chave-valor, pode haver requisitos adicionais, como enviar notificações quando um novo comentário é adicionado a uma reclamação ou executar consultas analíticas para descobrir a distribuição da reclamação por severidade (ou performance do agente) por semana. Um requisito adicional relacionado ao gerenciamento do ciclo de vida ou à conformidade seria arquivar os dados da reclamação após três anos de registro em log da reclamação.
Diagrama da arquitetura do sistema de gerenciamento de reclamações
O diagrama a seguir mostra o diagrama de arquitetura do sistema de gerenciamento de reclamações. Este diagrama mostra as diferentes integrações de AWS service (Serviço da AWS) que o sistema de gerenciamento de reclamações usa.

Além dos padrões de acesso transacional de chave-valor que trataremos posteriormente na seção de modelagem de dados do DynamoDB, temos três requisitos não transacionais. O diagrama de arquitetura acima pode ser dividido nestes três fluxos de trabalho:
-
Enviar uma notificação quando um novo comentário for adicionado a uma reclamação.
-
Executar consultas analíticas em dados semanais.
-
Arquivar dados com mais de três anos.
Vamos analisar mais profundamente cada um deles.
Enviar uma notificação quando um novo comentário for adicionado a uma reclamação.
Podemos usar o fluxo de trabalho abaixo para cumprir esse requisito:

DynamoDB Streams é um mecanismo de captura de dados de alterações para registrar todas as atividades de gravação em suas tabelas do DynamoDB. Você pode configurar funções do Lambda para acionar algumas ou todas essas alterações. Um filtro de eventos pode ser configurado em acionadores do Lambda para filtrar eventos que não são relevantes para o caso de uso. Nesse caso, podemos usar um filtro para acionar o Lambda somente quando um novo comentário é adicionado e enviar uma notificação aos IDs de e-mail relevantes, que podem ser obtidos no AWS Secrets Manager ou em qualquer outro repositório de credenciais.
Executar consultas analíticas em dados semanais.
O DynamoDB é adequado para workloads que se concentram principalmente no processamento transacional on-line (OLTP). Quanto aos 10% a 20% restantes dos padrões de acesso com requisitos analíticos, os dados podem ser exportados para o S3 com o atributo Exportar para o Amazon S3 sem impacto no tráfego em tempo real na tabela do DynamoDB. Veja este fluxo de trabalho abaixo:

O Amazon EventBridge pode ser usado para acionar AWS Lambda na programação: permite configurar uma expressão cron para que a invocação do Lambda ocorra periodicamente. O Lambda pode invocar a chamada de API ExportToS3
e armazenar dados do DynamoDB no S3. Esses dados do S3 podem então ser acessados por um mecanismo SQL como o Amazon Athena para executar consultas analíticas nos dados do DynamoDB sem afetar a workload transacional em tempo real na tabela. Um exemplo de consulta do Athena para encontrar o número de reclamações por nível de gravidade teria a aparência abaixo:
SELECT Item.severity.S as "Severity", COUNT(Item) as "Count"
FROM "complaint_management"."data"
WHERE NOT Item.severity.S = ''
GROUP BY Item.severity.S ;
Isso gera o seguinte resultado da consulta do Athena:

Arquivar dados com mais de três anos.
Você pode utilizar o atributo vida útil (TTL) do DynamoDB para excluir dados obsoletos da tabela do DynamoDB sem custo adicional (exceto no caso de réplicas de tabelas globais para a versão 2019.11.21 (atual), em que as exclusões TTL replicadas em outras regiões consomem capacidade de gravação). Esses dados aparecem e podem ser consumidos no DynamoDB Streams para serem arquivados no Amazon S3. O fluxo de trabalho referente a esse requisito é o seguinte:

Diagrama de relacionamento de entidades do sistema de gerenciamento de reclamações
Este é o diagrama de relacionamento de entidades (ERD) que usaremos para o design do esquema de gerenciamento de reclamações.

Padrões de acesso ao sistema de gerenciamento de reclamações
Estes são os padrões de acesso que vamos considerar para o design do esquema de gerenciamento de reclamações.
-
createComplaint
-
updateComplaint
-
updateSeveritybyComplaintID
-
getComplaintByComplaintID
-
addCommentByComplaintID
-
getAllCommentsByComplaintID
-
getLatestCommentByComplaintID
-
getAComplaintbyCustomerIDAndComplaintID
-
getAllComplaintsByCustomerID
-
escalateComplaintByComplaintID
-
getAllEscalatedComplaints
-
getEscalatedComplaintsByAgentID (ordem da mais recente para a mais antiga)
-
getCommentsByAgentID (entre duas datas)
Evolução do design do esquema do sistema de gerenciamento de reclamações
Como esse é um sistema de gerenciamento de reclamações, a maioria dos padrões de acesso gira em torno de uma reclamação como entidade primária. O ComplaintID
, por ser altamente cardinal, garantirá uma distribuição uniforme dos dados nas partições subjacentes e também é o critério de pesquisa mais comum para nossos padrões de acesso identificados. Portanto, ComplaintID
é um bom candidato à chave de partição nesse conjunto de dados.
Etapa 1: abordar os padrões de acesso 1 (createComplaint
), 2 (updateComplaint
), 3 (updateSeveritybyComplaintID
) e 4 (getComplaintByComplaintID
)
Podemos usar uma chave de classificação genérica chamada “metadados” (ou “AA”) para armazenar informações específicas da reclamação, como CustomerID
, State
, Severity
e CreationDate
. Usamos operações singleton com PK=ComplaintID
e SK=“metadata”
para fazer o seguinte:
-
PutItem
, para criar uma reclamação. -
UpdateItem
, para atualizar a gravidade ou outros campos nos metadados da reclamação. -
GetItem
, para buscar metadados para a reclamação.

Etapa 2: abordar o padrão de acesso 5 (addCommentByComplaintID
)
Esse padrão de acesso exige um modelo de relação de um para muitos entre uma reclamação e comentários sobre a reclamação. Utilizaremos a técnica particionamento vertical aqui para usar uma chave de classificação e criar uma coleção de itens com diferentes tipos de dados. Quando observarmos os padrões de acesso 6 (getAllCommentsByComplaintID
) e 7 (getLatestCommentByComplaintID
), sabemos que os comentários precisarão ser classificados por hora. Também podemos receber vários comentários ao mesmo tempo para que possamos usar a técnica chave de classificação composta para acrescentar tempo e CommentID
ao atributo de chave de classificação.
Uma opção para lidar com essas possíveis colisões de comentários seria aumentar o detalhamento do carimbo de data/hora ou adicionar um número incremental como sufixo em vez de usar Comment_ID
. Nesse caso, prefixaremos o valor da chave de classificação dos itens correspondentes aos comentários com “comm#” para permitir operações baseadas em intervalos.
Também precisamos garantir que o currentState
nos metadados da reclamação reflitam o estado quando um novo comentário for adicionado. Adicionar um comentário pode indicar que a reclamação foi atribuída a um agente ou resolvida etc. Para agrupar a adição de comentários e a atualização do estado atual nos metadados da reclamação, de uma maneira “tudo ou nada”, usaremos a API TransactWriteItems. O estado da tabela resultante agora tem a seguinte aparência:

Vamos adicionar mais alguns dados na tabela, e também ComplaintID
como um campo separado de nosso PK
, para preparar o modelo para o futuro, caso precisemos de outros índices em ComplaintID
. Observe também que alguns comentários podem ter anexos, os quais serão armazenados no Amazon Simple Storage Service e só terão as respectivas referências ou URLs mantidas no DynamoDB. É prática recomendada manter o banco de dados transacional o mais enxuto possível para otimizar o custo e a performance. O arquivo de dados agora é semelhante a:

Etapa 3: abordar os padrões de acesso 6 (getAllCommentsByComplaintID
) e 7 (getLatestCommentByComplaintID
)
Para receber todos os comentários de uma reclamação, podemos usar a operação query com a condição begins_with
na chave de classificação. Em vez de consumir capacidade adicional de leitura para ler a entrada de metadados e, depois, precisar lidar com a sobrecarga de filtrar os resultados relevantes, ter uma condição de chave de classificação como essa nos ajuda a ler apenas o que precisamos. Por exemplo, uma operação de consulta com PK=Complaint123
e SK
begins_with comm#
exibiria o seguinte ao ignorar a entrada de metadados:

Como precisamos do comentário mais recente para uma reclamação no padrão 7 (getLatestCommentByComplaintID
), vamos usar dois parâmetros de consulta adicionais:
-
ScanIndexForward
deve ser definido como False para receber resultados classificados em ordem decrescente. -
Limit
deve ser definido como 1 para receber o comentário mais recente (apenas um)..
Tal como no padrão de acesso 6 (getAllCommentsByComplaintID
), ignoramos a entrada de metadados usando begins_with
comm#
como a condição da chave de classificação. Agora você pode executar o padrão de acesso 7 nesse design usando a operação de consulta com PK=Complaint123
e SK=begins_with comm#
, ScanIndexForward=False
e Limit
1. O seguinte item direcionado será retornado como resultado:

Vamos adicionar mais dados fictícios à tabela.

Etapa 4: abordar os padrões de acesso 8 (getAComplaintbyCustomerIDAndComplaintID
) e 9 (getAllComplaintsByCustomerID
)
Os padrões de acesso 8 (getAComplaintbyCustomerIDAndComplaintID
) e 9 (getAllComplaintsByCustomerID
) introduzem um novo critério de pesquisa: CustomerID
. Buscá-lo na tabela existente exige uma Scan
cara, pois é necessário ler todos os dados e, depois, filtrar os itens relevantes para o CustomerID
em questão. Podemos tornar essa pesquisa mais eficiente criando um índice secundário global (GSI) com CustomerID
como a chave de partição. Tendo em mente a relação de um para muitos entre o cliente e as reclamações, bem como o padrão de acesso 9 (getAllComplaintsByCustomerID
), ComplaintID
seria o candidato certo para a chave de classificação.
Os dados no GSI ficariam assim:

Um exemplo de consulta nesse GSI para o padrão de acesso 8 (getAComplaintbyCustomerIDAndComplaintID
) seria: customer_id=custXYZ
, sort key=Complaint1321
. O resultado seria:

Para receber todas as reclamações de um cliente sobre o padrão de acesso 9 (getAllComplaintsByCustomerID
), a consulta no GSI seria: customer_id=custXYZ
como a condição da chave de partição. O resultado seria:

Etapa 5: abordar o padrão de acesso 10 (escalateComplaintByComplaintID
)
Esse acesso apresenta o aspecto de encaminhamento. Para encaminhar uma reclamação, podemos usar UpdateItem
para adicionar atributos como escalated_to
e escalation_time
ao item de metadados da reclamação existente. O DynamoDB fornece um design de esquema flexível, o que significa que um conjunto de atributos que não são de chave pode ser uniforme ou distinto em diferentes itens. Veja o seguinte exemplo:
UpdateItem with PK=Complaint1444, SK=metadata

Etapa 6: abordar os padrões de acesso 11 (getAllEscalatedComplaints
) e 12 (getEscalatedComplaintsByAgentID
)
Espera-se que apenas algumas reclamações sejam encaminhadas de todo o conjunto de dados. Portanto, criar um índice sobre os atributos relacionados ao encaminhamento resultaria em pesquisas eficientes e em um armazenamento GSI econômico. Podemos fazer isso utilizando a técnica índice esparso. O GSI com uma chave de partição como escalated_to
e uma chave de classificação como escalation_time
ficaria desta forma:

Para obter todas as reclamações encaminhadas ao padrão de acesso 11 (getAllEscalatedComplaints
), nós simplesmente verificamos esse GSI. Observe que essa verificação será eficiente e econômica devido ao tamanho do GSI. Para receber reclamações encaminhadas a um agente específico [padrão de acesso 12 (getEscalatedComplaintsByAgentID
)], a chave de partição seria escalated_to=agentID
, e definimos ScanIndexForward
como False
para classificação do mais novo para o mais antigo.
Etapa 7: abordar o padrão de acesso 13 (getCommentsByAgentID
)
Para o último padrão de acesso, precisamos pesquisar uma nova dimensão: AgentID
. Também precisamos de uma classificação baseada em tempo para ler os comentários entre duas datas. Portanto, criamos um GSI com agent_id
como a chave de partição e comm_date
como a chave de classificação. Os dados nesse GSI terão a seguinte aparência:

Um exemplo de consulta sobre esse GSI seria partition key agentID=AgentA
e sort key=comm_date between (2023-04-30T12:30:00, 2023-05-01T09:00:00)
, cujo resultado é:

Todos os padrões de acesso e a forma como o design do esquema os aborda estão resumidos na tabela abaixo:
Padrão de acesso | Tabela base/GSI/LSI | Operation | Valor da chave de partição | Valores de chave de classificação | Outras condições/filtros |
---|---|---|---|---|---|
createComplaint | Tabela base | PutItem | PK=complaint_id | SK=metadata | |
updateComplaint | Tabela base | UpdateItem | PK=complaint_id | SK=metadata | |
updateSeveritybyComplaintID | Tabela base | UpdateItem | PK=complaint_id | SK=metadata | |
getComplaintByComplaintID | Tabela base | GetItem | PK=complaint_id | SK=metadata | |
addCommentByComplaintID | Tabela base | TransactWriteItems | PK=complaint_id | SK=metadata, SK=comm#comm_date#comm_id | |
getAllCommentsByComplaintID | Tabela base | Consulta | PK=complaint_id | SK begins_with "comm#" | |
getLatestCommentByComplaintID | Tabela base | Consulta | PK=complaint_id | SK begins_with "comm#" | scan_index_forward=False, Limit 1 |
getAComplaintbyCustomerIDAndComplaintID | Customer_complaint_GSI | Consulta | customer_id=customer_id | complaint_id = complaint_id | |
getAllComplaintsByCustomerID | Customer_complaint_GSI | Consulta | customer_id=customer_id | N/D | |
escalateComplaintByComplaintID | Tabela base | UpdateItem | PK=complaint_id | SK=metadata | |
getAllEscalatedComplaints | Escalations_GSI | Verificar | N/D | N/D | |
getEscalatedComplaintsByAgentID (ordem da mais recente para a mais antiga) | Escalations_GSI | Consulta | escalated_to=agent_id | N/D | scan_index_forward=False |
getCommentsByAgentID (entre duas datas) | Agents_Comments_GSI | Consulta | agent_id=agent_id | SK entre (data1, data2) |
Esquema final do sistema de gerenciamento de reclamações
Veja aqui os designs do esquema final. Para baixar esse design de esquema como arquivo JSON, consulte DynamoDB Examples
Tabela base

Customer_Complaint_GSI

Escalations_GSI

Agents_Comments_GSI

Como usar o NoSQL Workbench com esse design de esquema
Você pode importar esse esquema final para o NoSQL Workbench, uma ferramenta visual que fornece atributos de modelagem de dados, visualização de dados e desenvolvimento de consultas para o DynamoDB, se quiser explorar e editar ainda mais seu novo projeto. Para começar, siga estas etapas:
-
Baixe o NoSQL Workbench. Para ter mais informações, consulte Baixar o NoSQL Workbench para DynamoDB.
-
Baixe o arquivo do esquema JSON listado acima, que já está no formato do modelo NoSQL Workbench.
-
Importe o arquivo do esquema JSON para o NoSQL Workbench. Para ter mais informações, consulte Importar um modelo de dados existente.
-
Depois de importar para o NOSQL Workbench, você pode editar o modelo de dados. Para ter mais informações, consulte Editar um modelo de dados existente.
-
Para visualizar o modelo de dados, adicionar dados de exemplo ou importar dados de exemplo de um arquivo CSV, use o atributo Visualizador de dados do NoSQL Workbench.