Skip to content

Commit

Permalink
docs: improve readme
Browse files Browse the repository at this point in the history
  • Loading branch information
HectorxH committed Nov 6, 2024
1 parent 0aea99a commit 375aede
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 118 deletions.
136 changes: 110 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,123 @@
# massive_db_loader
# Massive DB Loader

Esta es una herramienta que permite cargar un gran volumen de parquets en una base de datos PostgreSQL **nueva? existente?**.
Durante el proceso de carga se pueden definir mappings de columnas del schema del parquet al schema de la base de datos objetivo mediante un archivo de config.
Esta es una herramienta que permite cargar un gran volumen de datos a partir de
parquets a tablas en una base de datos PostgreSQL.
Esta herramienta cuenta con una interfaz mediante CLI, al igual que una libreria
para uso programatico.

Esta herramienta cuenta con una interfaz mediante CLI, al igual que una libreria para uso programatico.
Las tablas a las que se le cargaran datos deben existir anteriormente en la base
de datos.

## Mappings
## Instalacion

> [!WARNING]
> Esta seccion se encuentra WIP
Para instalar la herramienta basta con ejecutar:

```bash
poetry install
```

## Ejecucion

El programa puede ser ejecutado con el siguiente commando:

```bash
poetry run mdbl data-load --parquets <parquets_folder> --mapping <mappings.toml>
```

### parquets

La flag `--parquets` recibe la direccion a la carpeta base en donde se encuentran
los parquets, estos deben a su vez encontrarse en sub carpetas (el nombre de estas
es el que se utiliza en los mappings).

Un ejemplo de `parquets_folder` puede ser el siguiente:

- `/parquets`
- `/parquet1`
- `01.parquet`
- `02.parquet`
- `03.parquet`
- `/parquet2`
- `a.parquet`
- `b.parquet`
- `c.parquet`


el nombre de los archivos dentre de las sub carpetas no es importante.

Esta flag es opcional y por defecto se busca en el directorio `./parquets`.

### mapping

La flag `--mapping` recibe un archivo de mappings el cual puede ser un archivo
`TOML` o `YAML` que indica los mappings. Este campo es obligatorio.

Ejemplo de formato de archivo de mappings:

Se planea soportar mappings en TOML o YAML.
```TOML
# TOML
[nombre_tabla]
stage = 0
[tabla.mappings]
columna1 = { column = "columna_parquet3", type="int" }
columna2 = { column = "columna_parquet4", type="int" }
[[tables]]
from = "parquet1"
to = "table1"
[[tables.columns]]
from = "column_in_parquet_1"
to = "column_in_table_1"
[[tables.columns]]
from = "column_in_parquet_2"
to = "column_in_table_2"

[[tables]]
from = "parquet2"
to = "table2"
[[tables.columns]]
from = "column_in_parquet_1"
to = "column_in_table1"
```

```YAML
# YAML
nombre_tabla:
stage: 0
mappings:
columna1:
column: "columna_parquet3"
type: "int"
columna2:
column: "columna_parquet4"
type: "int"
tables:
- from: parquet1
to: table1
columns:
- from: column_in_parquet_1
to: column_in_table_1
- from: column_in_parquet_2
to: column_in_table_2
- from: parquet2
to: table2
columns:
- from: column_in_parquet_1
to: column_in_table_1
```
(stage en este caso seria el orden en que se deben ejecutar las cargas)
## Detalles de implementacion
> [!WARNING]
> El orden en el que se listan las tablas corresponde al orden en que se ejecutaran
> las inserciones. Esto se debe tener en consideracion a la hora de tratar con llaves
> primarias y foraneas.
Esta herramienta estara escrita en Python, utilizando la libreria Click para ofrecer su CLI.
Utilizaremos duckdb para ejecutar SQL en las bases de datos directamente, sin utilizar un ORM de por medio.
### Configuracion DB
Para conectarse a la base de datos el programa lee las siguientes variables de entorno
como configuracion:
```bash
DB_NAME="postgres"
DB_USER="postgres"
DB_HOST="localhost"
DB_PORT="5432"
DB_PASS="postgres"
```

Ademas es posible configurar estas variables directamente al llamar la aplicacion
de la siguiente forma.

```bash
poetry run mdbl \
--db-name postgres \
--db-user postgres \
--db-host localhost \
--db-port 5432 \
--db-pass postgres \
data-load --mapping mapping.yaml
```
5 changes: 5 additions & 0 deletions example.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
DB_NAME="postgres"
DB_USER="postgres"
DB_HOST="localhost"
DB_PORT="5432"
DB_PASS="postgres"
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ build-backend = "poetry.core.masonry.api"
reportAny = false
reportUnknownMemberType = false
reportUnusedCallResult = false
typeCheckingMode = "standard"

[tool.ruff]
target-version = "py312"
53 changes: 10 additions & 43 deletions src/mdbl/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,18 @@

import click
import duckdb
import psycopg

import mdbl.mdbl as mdbl
from mdbl import utils
from mdbl.models.cli import ValidFileTypes
from mdbl.models.mappings import DBMappings


@click.group
@click.option("--db-name", required=True, type=str, envvar="MDBL_DB_NAME")
@click.option("--db-user", required=True, type=str, envvar="MDBL_DB_USER")
@click.option("--db-host", required=True, type=str, envvar="MDBL_DB_HOST")
@click.option("--db-port", required=True, type=int, envvar="MDBL_DB_PORT")
@click.option("--db-pass", required=True, type=str, envvar="MDBL_DB_PASS")
@click.option("--db-name", required=True, type=str, envvar="DB_NAME")
@click.option("--db-user", required=True, type=str, envvar="DB_USER")
@click.option("--db-host", required=True, type=str, envvar="DB_HOST")
@click.option("--db-port", required=True, type=int, envvar="DB_PORT")
@click.option("--db-pass", required=True, type=str, envvar="DB_PASS")
@click.pass_context
def main(
ctx: click.Context,
Expand All @@ -27,7 +25,8 @@ def main(
db_pass: str,
):
"""
Main Group
MDBL:
Application to load large parquet files into a DB.
"""
con = duckdb.connect()
con.install_extension("postgres")
Expand Down Expand Up @@ -74,6 +73,9 @@ def data_load(
mapping: BinaryIO,
file_type: str,
):
"""
Loads the parquets into the database applying the especified mappings.
"""
con: duckdb.DuckDBPyConnection = obj["con"]
db_mappings = mdbl.read_mapping(mapping, ValidFileTypes(file_type))
try:
Expand All @@ -87,38 +89,3 @@ def data_load(
click.echo(f"\t> {e}")
finally:
con.close()


@click.group
def dev_utils():
pass


@dev_utils.command()
def generate_dummy_data():
utils.generate_dummy_parquets()


@dev_utils.command()
def recreate_tables():
with psycopg.connect(
"dbname=postgres user=postgres password=postgres host=127.0.0.1"
) as con:
with con.cursor() as cur:
cur.execute("""
DROP TABLE IF EXISTS objects CASCADE;
CREATE TABLE objects (
oid VARCHAR(255) PRIMARY KEY,
firstmjd VARCHAR(255),
ndet VARCHAR(255)
)
""")

cur.execute("""
DROP TABLE IF EXISTS detections CASCADE;
CREATE TABLE detections (
candid VARCHAR(255) PRIMARY KEY,
oid VARCHAR(255) REFERENCES objects(oid),
mag VARCHAR(255)
)
""")
49 changes: 0 additions & 49 deletions src/mdbl/utils.py

This file was deleted.

0 comments on commit 375aede

Please sign in to comment.