Começando uma API para Self-Service BI (Parte 1)
Acesso aos dados por meio do
Excel,
via
R
ou alguma
solução amigável
para analistas com ou sem familiaridade com
linguagens de programação
e
SQL,
erros no driver de conexão do
PowerBI
com nossa fonte de dados principal, enriquecimento de dados durante as transformações
nos pipelines, paixão por
JSON,
minha curiosidade e aprendizado contínuo foram motivos que me fizeram pensar que uma
API (Application Programming Interface)
poderia ser parte da nossa "stack de dados". Entendiamos que a descentralização do acesso aos
dados aumentaria a autonomia de muitos setores em suas análises, além de fomentar a
cultura de ser orientado por dados,
que era o objetivo da minha coordenação, compartilhado em meu post
Como foi ser um Estagiário de Dados?.
Hoje depois de um ano, provavelmente não a escolheria como primeira opção. Mas ter encarado o
desafio,
ver o projeto sendo utilizado e trabalhar nas melhorias, trouxe muitos aprendizados! Não está mais
em
funcionamento, pois optaram por adquirir uma plataforma baseada no
Apache Hadoop.
Recriei a estrutura para continuar
meus testes e descobertas
e validar a abordagem chamada de
Self-Service BI,
que permite que usuários de negócio acessem, explorem e visualizem dados sem
depender de muitos conhecimentos técnicos.
Para começar o desenvolvimento fiz pesquisas sobre a criação de uma
API,
e haviam muitos resultados que recomendavam e relacionavam a
"alto desempenho" e "escalabilidade" o
Node.js...
então, desapeguei-me do
Python.
Não demorou muito tempo para ter vários arquivos e uma dificuldade de manter organizado o projeto,
e por isso comecei a pensar como poderia diminuir as redundâncias e facilitar as inserções de
endpoints
e tecnologias. Analisando o que tinhamos mapeado de dados e regras de negócio durante a criação
dos
pipelines,
identifiquei três formas prováveis de requisições.
E os
Controllers:
Em
dates
é aceito duas datas no formato
ISO 8601,
como em
BETWEEN.
Já
multi
aceita um ou vários valores, como em
IN.
GetHandler
verifica se foram enviados os parâmetros, se são válidos e então cria um
objeto
com os dados da requisição (...vou falar mais sobre!).
Alguns
pipelines
e
dashboards
precisavam da última data existente nos dados, e por isso também aceitava receber como valor:
max.
Mesmo que seja possível direcionar as requisições para um único
controller,
a validação será específica. Com o tempo, dependendo da quantidade e diversidade de consultas,
fica grande e inviável de manter. Por isso sempre que possível direcionava para
dates,
pois para análise de dados períodos são relevantes. Mas, continuo buscando alternativas.
Por fim:
noparams.
É para requisições sem parâmetros, ideal para baixo/médio volume, pois retorna todos os dados.
Seu foco eram os dados que complementam e enriquecem as tranformações no
ETL.
Em algumas consultas, dependendo do cliente/usuário dos dados, aconteceria
over-fetching
ou
under-fetching.
Pesquisando descobri que
GraphQL
poderia me ajudar e não precisaria me desfazer da estrutura
REST,
pois o
Express.js
conseguiria trabalhar simultaneamente com as duas arquiteturas.
Nesse ponto fiz alguns testes e resolvi armazenar alguns dados no
MongoDB.
Um dos motivos foi o método
populate
da biblioteca
mongoose,
que permite substituir referências em um documento
(...como IDs de outros documentos!) por seus documentos relacionados,
ou seja, ao invés de várias consultas separadas, possibilita buscar
dados em uma única consulta.
Agora tinham requisições com estruturas diferentes sendo direcionadas
para o
Sequelize
e
mongoose
que trabalham de forma distinta.
Então para que fosse independente da "origem" e "destino", a solução foi criar um
objeto
para padronizar a consulta, como abordarei na
Parte 2.
E você, o que achou? Como faria?
Obrigado pela leitura.