Pipeline ELT end-to-end para analizar la evolución semanal del ranking New York Times Hardcover Fiction, enriquecido con metadata editorial de Google Books y señales de atención pública de Wikipedia Pageviews.
Fiction Weekly Radar integra múltiples APIs heterogéneas, centraliza los datos en un warehouse analítico, aplica modelado con dbt y expone una capa final de consumo optimizada para BI.
La solución fue construida con el siguiente stack:
- Airbyte para extracción y carga
- MotherDuck / DuckDB como warehouse
- dbt + dbt-expectations para transformación, testing y documentación
- Prefect + prefect-dbt para orquestación
- Metabase para visualización
El proyecto sigue un enfoque ELT y un modelo híbrido Kimball + One Big Table (OBT):
- Kimball aporta estructura analítica, gobernanza y reutilización
- OBT simplifica el consumo en BI y reduce joins en la capa de visualización
Construir un radar semanal que permita analizar:
- desempeño editorial del ranking NYT
- permanencia y dinámica de los libros en el ranking
- contexto editorial y reputación desde Google Books
- atención pública digital desde Wikipedia Pageviews
Fuentes externas
├── NYT Books API
├── Google Books API
└── Wikipedia Pageviews API
↓
Ingesta (Airbyte)
↓
Raw (MotherDuck / schema main)
↓
Transformación y calidad (dbt)
↓
Capa semántica final (OBT)
↓
Orquestación (Prefect)
↓
BI / Dashboard (Metabase)
- separación clara entre ingesta, almacenamiento, transformación, orquestación y visualización
- trazabilidad de datos desde raw hasta BI
- modularidad y mantenibilidad
- reproducibilidad de la ejecución
Fuente principal del proyecto.
Granularidad: Libro – Semana
Aporta:
- ranking semanal
- título
- autor
- editorial
- semanas en lista
- ranking de la semana anterior
- URL de Amazon
- imagen del libro
Fuente de enriquecimiento editorial.
Granularidad: Libro
Aporta:
- publisher
- published date
- categories
- language
- average rating
- ratings count
Fuente de atención pública digital.
Granularidad: Autor – Día
Aporta:
- views por artículo
- granularidad temporal diaria
- series temporales para agregación semanal
Se utilizaron 2 conexiones finales:
nyt_parent_googlebookswiki_pageviews
Se definió una estrategia append-only sobre la capa raw:
hardcover_fiction_by_date(NYT) →Full refresh | Appendvolumes_by_isbn(Google Books) →Full refresh | Appendpageviews_by_article(Wikipedia) →Full refresh | Append
La capa raw se diseñó como una landing histórica e inmutable, priorizando:
- historización
- trazabilidad
- reprocesamiento
- separación entre ingesta y transformación
La deduplicación lógica, la integración entre granularidades y la definición del grano analítico final se resuelven en dbt.
airbyte_curso.main
Contiene las tablas cargadas por Airbyte sin transformar.
airbyte_curso.dbt_final
Contiene:
- staging
- intermediate
- marts
- OBT final
models/proyecto_final/
├── staging/
├── intermediate/
├── marts/
└── obt/
stg_*→ limpieza, tipificación y normalización inicialint_*→ construcción de llaves, desacople lógico y normalizacióndim_*,fct_*,bridge_*→ modelo dimensionalobt_*→ tabla final optimizada para BI
Las fuentes externas se declararon en:
models/staging/_sources.yml
con:
database: airbyte_cursoschema: main
Se utilizó:
source()para referenciar tablas rawref()para dependencias entre modelos internos
Incluye:
- dimensiones de libro, autor, semana y fecha
- facts de ranking NYT, snapshots de Google Books y pageviews
- bridge table libro–autor
Tabla de consumo analítico:
airbyte_curso.dbt_final.obt_fiction_weekly_scorecard
Ventajas:
- elimina joins en la capa BI
- simplifica consultas
- mejora performance en Metabase
- conserva una narrativa analítica clara
La estrategia de materialización quedó definida así:
staging→viewintermediate→viewmarts→tableobt→table
viewen capas tempranas para mantener flexibilidad y evitar persistencia innecesariatableen marts y OBT para optimizar consumo analítico y consultas frecuentes
La calidad se trató como parte estructural del pipeline.
- integridad
- completitud
- validez
- cobertura
- consistencia referencial
Se aplicaron:
not_nulluniquerelationships
Se implementaron validaciones sobre:
- unicidad compuesta
- volumen esperado
- obligatoriedad de campos
- rangos válidos
- regex
- dominios cerrados
La corrida consolidada del proyecto finalizó con:
PASS=75 WARN=0 ERROR=0 SKIP=0 NO-OP=0 TOTAL=75
La orquestación se implementó en:
prefect_flows/pipeline_proyecto_final.py
@flowpara el proceso coordinador principal@taskpara autenticación, disparo de syncs, espera de jobs y ejecución de dbt
- obtener token de Airbyte
- ejecutar sync de
nyt_parent_googlebooks - esperar finalización del job
- ejecutar sync de
wiki_pageviews - esperar finalización del job
- ejecutar
dbt deps - ejecutar
dbt build
La ejecución de dbt se resolvió con:
prefect-dbtPrefectDbtRunner
El flow incorpora:
- retries en
trigger_sync() - polling con timeout en
wait_job() - refresh de token ante
401 - validación temprana de variables de entorno
- logs centralizados en Prefect UI
Deployment local:
pf-semanal
Schedule:
todos los lunes a las 06:00
timezone = America/Asuncion
El dashboard final consume directamente la tabla:
airbyte_curso.dbt_final.obt_fiction_weekly_scorecard
Visualizar:
- desempeño semanal del ranking
- dinámica y permanencia
- metadata editorial
- atención pública digital
- This Week’s Winners
- Who Are They?
- Public Attention
Se implementó un filtro por semana basado en:
published_date
- KPI de control del ranking
- Top 15 por semana
- movers positivos
- movers negativos
- nuevos ingresos
- métricas de views 7d
.
├── models/
│ └── proyecto_final/
│ ├── staging/
│ ├── intermediate/
│ ├── marts/
│ └── obt/
├── prefect_flows/
│ ├── pipeline_proyecto_final.py
│ └── .env
├── macros/
├── tests/
├── dbt_project.yml
├── packages.yml
├── profiles.yml # no versionar si contiene credenciales reales
└── README.md
Crear el archivo:
prefect_flows/.env
con al menos:
AIRBYTE_PUBLIC_API_URL=http://localhost:8000/api/public/v1
AIRBYTE_CLIENT_ID=TU_CLIENT_ID
AIRBYTE_CLIENT_SECRET=TU_CLIENT_SECRET
AIRBYTE_CONN_ID_NYT_PARENT_GBOOKS=TU_CONNECTION_ID_NYT
AIRBYTE_CONN_ID_WIKI_PAGEVIEWS=TU_CONNECTION_ID_WIKI
DBT_PROJECT_DIR=/home/mti2_ubuntu/projects/dbt/mi_proyecto_dbt
DBT_PROFILES_DIR=/home/mti2_ubuntu/.dbt
DBT_TARGET=final
DBT_SELECT=path:models/proyecto_finalEsta sección está pensada como runbook operativo para reproducir el proyecto de punta a punta.
Antes de ejecutar, verificar:
- Airbyte local operativo
- MotherDuck accesible
- perfil dbt configurado correctamente
- credenciales válidas en
prefect_flows/.env - proyecto ubicado en
~/projects/dbt/mi_proyecto_dbt
dbt-envpara ejecución manual de dbtprefect-envpara ejecución del flow de Prefect
cd ~/projects/dbt/mi_proyecto_dbt
source /home/mti2_ubuntu/dbt-env/bin/activateVerificación opcional:
which python
which dbtdbt depsdbt build --target final --select path:models/proyecto_finaldbt docs generate --target final
dbt docs serveLa corrida final debería terminar sin errores y con evidencia similar a:
PASS=75 WARN=0 ERROR=0
Si ya estás dentro de otra venv:
deactivateLuego:
cd ~/projects/dbt/mi_proyecto_dbt
source prefect_flows/prefect-env/bin/activateprefect server startAbrir en navegador:
http://127.0.0.1:4200
En otra terminal, con prefect-env activo:
cd ~/projects/dbt/mi_proyecto_dbt
source prefect_flows/prefect-env/bin/activate
python prefect_flows/pipeline_proyecto_final.pyEsto deja disponible el deployment:
pf-semanal
Para correr el pipeline completo ad hoc:
cd ~/projects/dbt/mi_proyecto_dbt
source prefect_flows/prefect-env/bin/activate
python - <<'PY'
from prefect_flows.pipeline_proyecto_final import airbyte_and_dbt_flow
airbyte_and_dbt_flow()
print("FLOW_OK")
PY- sync exitoso de NYT/Google Books
- sync exitoso de Wikipedia
- ejecución satisfactoria de
dbt deps - ejecución satisfactoria de
dbt build - salida final:
FLOW_OK
La reproducción se considera correcta cuando se cumplen simultáneamente estas condiciones:
- ambas conexiones de Airbyte terminan exitosamente
- el flow aparece en Prefect UI
- el run finaliza en estado
Completed dbt build --target final --select path:models/proyecto_finalfinaliza sin errores- la tabla
airbyte_curso.dbt_final.obt_fiction_weekly_scorecardqueda disponible - la evidencia final de tests muestra:
PASS=75 WARN=0 ERROR=0
Verificar:
AIRBYTE_CLIENT_IDAIRBYTE_CLIENT_SECRETAIRBYTE_PUBLIC_API_URL
Verificar que prefect server start esté levantado y que el flow se ejecute con prefect-env.
Instalar en el entorno correspondiente:
pip install -U dbt-duckdbEjecutar:
dbt depsdbt deps
dbt build --target final --select path:models/proyecto_final
dbt docs generate --target final
dbt docs serveprefect server start
python prefect_flows/pipeline_proyecto_final.py
python - <<'PY'
from prefect_flows.pipeline_proyecto_final import airbyte_and_dbt_flow
airbyte_and_dbt_flow()
print("FLOW_OK")
PY- arquitectura implementada
- ingesta en Airbyte operativa
- modelo dbt construido
- tests ejecutados satisfactoriamente
- orquestación semanal implementada
- dashboard final en Metabase disponible
- Fátima Barrios
- Claudia Coronel
- Graciela Vera