- Migrate from SQLite to PostgreSQL with normalized schema - Add 11 lookup tables (fuel_type, body_type, drivetrain, transmission, materials, position_part, manufacture_type, quality_tier, countries, reference_type, shapes) - Rewrite dashboard/server.py (76 routes) using SQLAlchemy text() queries - Rewrite console/db.py (27 methods) using SQLAlchemy ORM - Add models.py with 27 SQLAlchemy model definitions - Add config.py for centralized DB_URL configuration - Add migrate_to_postgres.py migration script - Add docs/METABASE_GUIDE.md with complete data entry guide - Rebrand from "AUTOPARTS DB" to "NEXUS AUTOPARTS" - Fill vehicle data gaps via NHTSA API + heuristics: engines (cylinders, power, torque), brands (country, founded_year), models (body_type, production years), MYE (drivetrain, transmission, trim) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
426 lines
12 KiB
Markdown
426 lines
12 KiB
Markdown
# Documentación de Base de Datos - Nexus Autoparts
|
|
|
|
## Resumen
|
|
|
|
La base de datos utiliza SQLite 3 y está diseñada con un esquema normalizado para gestionar información de vehículos de manera eficiente.
|
|
|
|
**Archivo:** `vehicle_database/vehicle_database.db`
|
|
|
|
## Estadísticas Actuales
|
|
|
|
| Tabla | Registros |
|
|
|-------|-----------|
|
|
| brands | 12 |
|
|
| models | 10,923 |
|
|
| engines | 10,919 |
|
|
| years | ~35 |
|
|
| model_year_engine | 12,075 |
|
|
|
|
---
|
|
|
|
## Diagrama Entidad-Relación
|
|
|
|
```
|
|
┌──────────────┐
|
|
│ brands │
|
|
├──────────────┤
|
|
│ id (PK) │
|
|
│ name │
|
|
│ country │
|
|
│ founded_year │
|
|
│ created_at │
|
|
└──────┬───────┘
|
|
│
|
|
│ 1:N
|
|
│
|
|
┌──────▼───────────────┐
|
|
│ models │
|
|
├──────────────────────┤
|
|
│ id (PK) │
|
|
│ brand_id (FK) │───────────────────────┐
|
|
│ name │ │
|
|
│ body_type │ │
|
|
│ generation │ │
|
|
│ production_start_year│ │
|
|
│ production_end_year │ │
|
|
│ created_at │ │
|
|
└──────────────────────┘ │
|
|
│
|
|
┌──────────────────────┐ │
|
|
│ years │ │
|
|
├──────────────────────┤ │
|
|
│ id (PK) │───────────────┐ │
|
|
│ year │ │ │
|
|
│ created_at │ │ │
|
|
└──────────────────────┘ │ │
|
|
│ │
|
|
┌──────────────────────┐ │ │
|
|
│ engines │ │ │
|
|
├──────────────────────┤ │ │
|
|
│ id (PK) │───────┐ │ │
|
|
│ name │ │ │ │
|
|
│ displacement_cc │ │ │ │
|
|
│ cylinders │ │ │ │
|
|
│ fuel_type │ │ │ │
|
|
│ power_hp │ │ │ │
|
|
│ torque_nm │ │ │ │
|
|
│ engine_code │ │ │ │
|
|
│ created_at │ │ │ │
|
|
└──────────────────────┘ │ │ │
|
|
│ │ │
|
|
│ N:1 │ N:1 │ N:1
|
|
│ │ │
|
|
┌──────▼───────▼───────▼──────┐
|
|
│ model_year_engine │
|
|
├─────────────────────────────┤
|
|
│ id (PK) │
|
|
│ model_id (FK) │
|
|
│ year_id (FK) │
|
|
│ engine_id (FK) │
|
|
│ trim_level │
|
|
│ drivetrain │
|
|
│ transmission │
|
|
│ created_at │
|
|
└─────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Definición de Tablas
|
|
|
|
### Tabla: brands
|
|
|
|
Almacena información de los fabricantes de vehículos.
|
|
|
|
```sql
|
|
CREATE TABLE brands (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
name TEXT NOT NULL UNIQUE,
|
|
country TEXT,
|
|
founded_year INTEGER,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
```
|
|
|
|
| Campo | Tipo | Restricciones | Descripción |
|
|
|-------|------|---------------|-------------|
|
|
| id | INTEGER | PK, AUTO | Identificador único |
|
|
| name | TEXT | NOT NULL, UNIQUE | Nombre de la marca |
|
|
| country | TEXT | - | País de origen |
|
|
| founded_year | INTEGER | - | Año de fundación |
|
|
| created_at | TIMESTAMP | DEFAULT NOW | Fecha de creación |
|
|
|
|
**Índices:**
|
|
- `idx_brands_name` en `name`
|
|
|
|
---
|
|
|
|
### Tabla: models
|
|
|
|
Almacena información de los modelos de vehículos.
|
|
|
|
```sql
|
|
CREATE TABLE models (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
brand_id INTEGER NOT NULL,
|
|
name TEXT NOT NULL,
|
|
body_type TEXT,
|
|
generation TEXT,
|
|
production_start_year INTEGER,
|
|
production_end_year INTEGER,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (brand_id) REFERENCES brands(id),
|
|
UNIQUE(brand_id, name, generation)
|
|
);
|
|
```
|
|
|
|
| Campo | Tipo | Restricciones | Descripción |
|
|
|-------|------|---------------|-------------|
|
|
| id | INTEGER | PK, AUTO | Identificador único |
|
|
| brand_id | INTEGER | FK, NOT NULL | Referencia a brands |
|
|
| name | TEXT | NOT NULL | Nombre del modelo |
|
|
| body_type | TEXT | - | Tipo de carrocería |
|
|
| generation | TEXT | - | Generación del modelo |
|
|
| production_start_year | INTEGER | - | Año inicio producción |
|
|
| production_end_year | INTEGER | - | Año fin producción |
|
|
| created_at | TIMESTAMP | DEFAULT NOW | Fecha de creación |
|
|
|
|
**Valores de body_type:**
|
|
- Sedan, Coupe, Hatchback, SUV, Crossover, Truck, Van, Wagon, Convertible
|
|
|
|
**Índices:**
|
|
- `idx_models_brand_id` en `brand_id`
|
|
- `idx_models_name` en `name`
|
|
|
|
---
|
|
|
|
### Tabla: engines
|
|
|
|
Almacena especificaciones técnicas de los motores.
|
|
|
|
```sql
|
|
CREATE TABLE engines (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
name TEXT NOT NULL,
|
|
displacement_cc INTEGER,
|
|
cylinders INTEGER,
|
|
fuel_type TEXT,
|
|
power_hp INTEGER,
|
|
torque_nm INTEGER,
|
|
engine_code TEXT,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
UNIQUE(name, engine_code)
|
|
);
|
|
```
|
|
|
|
| Campo | Tipo | Restricciones | Descripción |
|
|
|-------|------|---------------|-------------|
|
|
| id | INTEGER | PK, AUTO | Identificador único |
|
|
| name | TEXT | NOT NULL | Nombre descriptivo |
|
|
| displacement_cc | INTEGER | - | Cilindrada en cc |
|
|
| cylinders | INTEGER | - | Número de cilindros |
|
|
| fuel_type | TEXT | - | Tipo de combustible |
|
|
| power_hp | INTEGER | - | Potencia en HP |
|
|
| torque_nm | INTEGER | - | Torque en Nm |
|
|
| engine_code | TEXT | - | Código del fabricante |
|
|
| created_at | TIMESTAMP | DEFAULT NOW | Fecha de creación |
|
|
|
|
**Valores de fuel_type:**
|
|
- Gasoline, Diesel, Hybrid, Electric, Plug-in Hybrid, Flex Fuel
|
|
|
|
**Índices:**
|
|
- `idx_engines_name` en `name`
|
|
- `idx_engines_code` en `engine_code`
|
|
|
|
---
|
|
|
|
### Tabla: years
|
|
|
|
Tabla de referencia para años de producción.
|
|
|
|
```sql
|
|
CREATE TABLE years (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
year INTEGER NOT NULL UNIQUE,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
```
|
|
|
|
| Campo | Tipo | Restricciones | Descripción |
|
|
|-------|------|---------------|-------------|
|
|
| id | INTEGER | PK, AUTO | Identificador único |
|
|
| year | INTEGER | NOT NULL, UNIQUE | Año |
|
|
| created_at | TIMESTAMP | DEFAULT NOW | Fecha de creación |
|
|
|
|
---
|
|
|
|
### Tabla: model_year_engine
|
|
|
|
Tabla de unión que relaciona modelos, años y motores.
|
|
|
|
```sql
|
|
CREATE TABLE model_year_engine (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
model_id INTEGER NOT NULL,
|
|
year_id INTEGER NOT NULL,
|
|
engine_id INTEGER NOT NULL,
|
|
trim_level TEXT,
|
|
drivetrain TEXT,
|
|
transmission TEXT,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (model_id) REFERENCES models(id),
|
|
FOREIGN KEY (year_id) REFERENCES years(id),
|
|
FOREIGN KEY (engine_id) REFERENCES engines(id),
|
|
UNIQUE(model_id, year_id, engine_id, trim_level)
|
|
);
|
|
```
|
|
|
|
| Campo | Tipo | Restricciones | Descripción |
|
|
|-------|------|---------------|-------------|
|
|
| id | INTEGER | PK, AUTO | Identificador único |
|
|
| model_id | INTEGER | FK, NOT NULL | Referencia a models |
|
|
| year_id | INTEGER | FK, NOT NULL | Referencia a years |
|
|
| engine_id | INTEGER | FK, NOT NULL | Referencia a engines |
|
|
| trim_level | TEXT | - | Nivel de equipamiento |
|
|
| drivetrain | TEXT | - | Tipo de tracción |
|
|
| transmission | TEXT | - | Tipo de transmisión |
|
|
| created_at | TIMESTAMP | DEFAULT NOW | Fecha de creación |
|
|
|
|
**Valores de drivetrain:**
|
|
- FWD (Front-Wheel Drive), RWD (Rear-Wheel Drive), AWD (All-Wheel Drive), 4WD (Four-Wheel Drive)
|
|
|
|
**Valores de transmission:**
|
|
- Manual, Automatic, CVT, DCT, AMT
|
|
|
|
**Índices:**
|
|
- `idx_mye_model_id` en `model_id`
|
|
- `idx_mye_year_id` en `year_id`
|
|
- `idx_mye_engine_id` en `engine_id`
|
|
|
|
---
|
|
|
|
## Consultas Comunes
|
|
|
|
### Obtener todos los vehículos de una marca
|
|
|
|
```sql
|
|
SELECT
|
|
b.name AS brand,
|
|
m.name AS model,
|
|
y.year,
|
|
e.name AS engine,
|
|
mye.trim_level,
|
|
mye.drivetrain,
|
|
mye.transmission
|
|
FROM model_year_engine mye
|
|
JOIN models m ON mye.model_id = m.id
|
|
JOIN brands b ON m.brand_id = b.id
|
|
JOIN years y ON mye.year_id = y.id
|
|
JOIN engines e ON mye.engine_id = e.id
|
|
WHERE b.name = 'Toyota'
|
|
ORDER BY m.name, y.year;
|
|
```
|
|
|
|
### Buscar vehículos por año
|
|
|
|
```sql
|
|
SELECT
|
|
b.name AS brand,
|
|
m.name AS model,
|
|
e.name AS engine,
|
|
e.power_hp,
|
|
mye.trim_level
|
|
FROM model_year_engine mye
|
|
JOIN models m ON mye.model_id = m.id
|
|
JOIN brands b ON m.brand_id = b.id
|
|
JOIN years y ON mye.year_id = y.id
|
|
JOIN engines e ON mye.engine_id = e.id
|
|
WHERE y.year = 2020;
|
|
```
|
|
|
|
### Obtener especificaciones de motor
|
|
|
|
```sql
|
|
SELECT
|
|
name,
|
|
displacement_cc,
|
|
cylinders,
|
|
fuel_type,
|
|
power_hp,
|
|
torque_nm,
|
|
engine_code
|
|
FROM engines
|
|
WHERE cylinders = 6
|
|
ORDER BY power_hp DESC;
|
|
```
|
|
|
|
### Contar modelos por marca
|
|
|
|
```sql
|
|
SELECT
|
|
b.name AS brand,
|
|
COUNT(DISTINCT m.id) AS model_count
|
|
FROM brands b
|
|
LEFT JOIN models m ON b.id = m.brand_id
|
|
GROUP BY b.id
|
|
ORDER BY model_count DESC;
|
|
```
|
|
|
|
### Buscar motores por potencia
|
|
|
|
```sql
|
|
SELECT *
|
|
FROM engines
|
|
WHERE power_hp >= 300
|
|
ORDER BY power_hp DESC;
|
|
```
|
|
|
|
---
|
|
|
|
## Mantenimiento
|
|
|
|
### Backup de la Base de Datos
|
|
|
|
```bash
|
|
# Crear backup
|
|
sqlite3 vehicle_database.db ".backup 'backup.db'"
|
|
|
|
# O usando cp
|
|
cp vehicle_database.db vehicle_database_backup_$(date +%Y%m%d).db
|
|
```
|
|
|
|
### Optimización
|
|
|
|
```sql
|
|
-- Analizar tablas para optimizar consultas
|
|
ANALYZE;
|
|
|
|
-- Reconstruir índices
|
|
REINDEX;
|
|
|
|
-- Compactar base de datos
|
|
VACUUM;
|
|
```
|
|
|
|
### Verificar Integridad
|
|
|
|
```sql
|
|
PRAGMA integrity_check;
|
|
PRAGMA foreign_key_check;
|
|
```
|
|
|
|
---
|
|
|
|
## Conexión desde Python
|
|
|
|
```python
|
|
import sqlite3
|
|
|
|
# Conectar a la base de datos
|
|
conn = sqlite3.connect('vehicle_database/vehicle_database.db')
|
|
conn.row_factory = sqlite3.Row # Permite acceso por nombre de columna
|
|
|
|
# Crear cursor
|
|
cursor = conn.cursor()
|
|
|
|
# Ejecutar consulta
|
|
cursor.execute("""
|
|
SELECT b.name, m.name, y.year
|
|
FROM model_year_engine mye
|
|
JOIN models m ON mye.model_id = m.id
|
|
JOIN brands b ON m.brand_id = b.id
|
|
JOIN years y ON mye.year_id = y.id
|
|
WHERE b.name = ?
|
|
""", ('Toyota',))
|
|
|
|
# Obtener resultados
|
|
for row in cursor.fetchall():
|
|
print(f"{row['name']} - {row['name']} ({row['year']})")
|
|
|
|
# Cerrar conexión
|
|
conn.close()
|
|
```
|
|
|
|
---
|
|
|
|
## Migración de Datos
|
|
|
|
### Exportar a CSV
|
|
|
|
```bash
|
|
sqlite3 -header -csv vehicle_database.db "SELECT * FROM brands;" > brands_export.csv
|
|
sqlite3 -header -csv vehicle_database.db "SELECT * FROM models;" > models_export.csv
|
|
sqlite3 -header -csv vehicle_database.db "SELECT * FROM engines;" > engines_export.csv
|
|
```
|
|
|
|
### Importar desde CSV
|
|
|
|
```bash
|
|
sqlite3 vehicle_database.db <<EOF
|
|
.mode csv
|
|
.import brands.csv brands
|
|
.import models.csv models
|
|
.import engines.csv engines
|
|
EOF
|
|
```
|