Diagrama de Base de Datos - Sherlock-docs¶
Descripción¶
Diagrama entidad-relación (ER) del esquema SQLite con soporte FTS5 para búsqueda full-text. Incluye tablas principales, índices, triggers y tabla virtual FTS5.
Motor: SQLite 3.9+ con extensión FTS5 Modo: WAL (Write-Ahead Logging) para mejor concurrencia
Diagrama ER¶
erDiagram
documents {
TEXT id PK "UUID v4"
TEXT file_path "Ruta absoluta al PDF"
TEXT file_name "Nombre del archivo"
TEXT document_type "tutela|habeas_corpus|unknown"
TEXT status "pending|processing|processed|validated|error"
TEXT content "Texto extraído por OCR o nativo"
REAL ocr_confidence "0.0-1.0 confianza OCR"
TEXT file_hash "SHA-256 binario del PDF"
INTEGER file_size_bytes "Tamaño del PDF en bytes"
TEXT demandante "Entidad extraída por NER"
TEXT demandado "Entidad extraída por NER"
TEXT radicado "Número de radicado"
TEXT juzgado "Juzgado asignado"
TEXT fecha_documento "Fecha del documento"
TEXT correo "Email extraído por NER"
TEXT cedula "CC/CE/NIT extraído por NER"
TEXT hora_radicacion "HH:MM:SS auto-generado"
TEXT numero_acta "~7 dígitos manual"
TEXT observaciones "Texto libre notas"
TEXT etiquetas "JSON array tags"
TEXT direccion_demandante "Dirección NER+manual"
TEXT direccion_demandado "Dirección NER+manual"
TEXT secuencia_anterior "Referencia doc previo"
TEXT coordenada "Coordenada geográfica"
INTEGER has_provisional_measure "1 si medida provisional"
TEXT provisional_keywords "JSON keywords detectadas"
INTEGER has_hechos "1 si sección hechos detectada"
INTEGER has_pretensiones "1 si sección pretensiones detectada"
INTEGER is_manual_entry "1 si ingreso manual"
TEXT processing_cancelled_at "Timestamp si cancelado"
TEXT imported_at "Timestamp de importación Excel"
TEXT created_at "ISO 8601 timestamp"
TEXT updated_at "ISO 8601 timestamp"
}
corrections {
INTEGER id PK "AUTOINCREMENT"
TEXT document_id FK "Referencias documents.id"
TEXT field_name "Campo corregido"
TEXT original_value "Valor original NER"
TEXT corrected_value "Valor corregido usuario"
TEXT corrected_by "username autenticado (GOB-05)"
TEXT created_at "ISO 8601 timestamp"
}
processing_stats {
INTEGER id PK "AUTOINCREMENT"
TEXT document_id FK "Referencias documents.id"
TEXT ocr_engine "tesseract|paddleocr|native"
REAL ocr_time_ms "Tiempo OCR en ms"
REAL ner_time_ms "Tiempo NER en ms"
REAL dedup_time_ms "Tiempo dedup en ms"
REAL total_time_ms "Tiempo total pipeline"
INTEGER pages_processed "Páginas procesadas"
INTEGER file_size_bytes "Tamaño del PDF"
TEXT spacy_model_version "Versión modelo SpaCy"
TEXT ocr_engine_version "Versión motor OCR"
TEXT dedup_config_snapshot "JSON config dedup"
TEXT created_at "ISO 8601 timestamp"
}
documents_fts {
TEXT content "Texto indexado FTS5"
TEXT demandante "Indexado FTS5"
TEXT demandado "Indexado FTS5"
TEXT radicado "Indexado FTS5"
TEXT juzgado "Indexado FTS5"
TEXT cedula "Indexado FTS5"
TEXT correo "Indexado FTS5"
TEXT numero_acta "Indexado FTS5"
TEXT observaciones "Indexado FTS5"
}
logs {
INTEGER id PK "AUTOINCREMENT"
TEXT timestamp "ISO 8601 del evento"
TEXT level "DEBUG|INFO|WARNING|ERROR|CRITICAL"
INTEGER level_no "Nivel numérico (10-50)"
TEXT logger_name "Nombre del logger"
TEXT module "Módulo Python"
TEXT func_name "Función origen"
INTEGER line_no "Línea de código"
TEXT message "Mensaje de log"
TEXT exception "Stack trace si aplica"
INTEGER process_id "PID del proceso"
INTEGER thread_id "ID del thread"
TEXT thread_name "Nombre del thread"
TEXT created_at "ISO 8601 de inserción"
}
audit_events {
INTEGER id PK "AUTOINCREMENT"
TEXT user_id "Usuario que ejecutó la acción"
TEXT action "document_processed|document_corrected|etc"
TEXT resource_type "document|import|export|session"
TEXT resource_id "ID del recurso afectado"
TEXT details "JSON detalles adicionales"
TEXT ip_address "IP del cliente"
TEXT created_at "ISO 8601 timestamp"
}
documents ||--o{ corrections : "tiene (ON DELETE CASCADE)"
documents ||--o| processing_stats : "tiene (ON DELETE CASCADE)"
documents ||--|| documents_fts : "sincroniza via triggers"
documents ||--o{ audit_events : "genera"
Tablas Principales¶
1. documents - Tabla Principal¶
Almacena todos los documentos legales procesados.
| Columna | Tipo | Restricción | Descripción |
|---|---|---|---|
id |
TEXT | PK | UUID v4 generado |
file_path |
TEXT | NOT NULL | Ruta absoluta al archivo PDF |
file_name |
TEXT | NOT NULL | Nombre del archivo original |
document_type |
TEXT | DEFAULT 'unknown' | Tipo: tutela, habeas_corpus, unknown |
status |
TEXT | DEFAULT 'pending' | Estado: pending, processing, processed, validated, error |
content |
TEXT | DEFAULT '' | Texto extraído por OCR o texto nativo |
ocr_confidence |
REAL | DEFAULT 0.0 | Confianza del OCR (0.0-1.0; 0.99 si nativo) |
file_hash |
TEXT | DEFAULT '' | Hash SHA-256 binario del PDF (gate pre-OCR) |
file_size_bytes |
INTEGER | DEFAULT 0 | Tamaño del PDF en bytes (gate pre-OCR) |
demandante |
TEXT | DEFAULT '' | Demandante extraído por NER |
demandado |
TEXT | DEFAULT '' | Demandado extraído por NER |
radicado |
TEXT | DEFAULT '' | Número de radicado |
juzgado |
TEXT | DEFAULT '' | Juzgado asignado |
fecha_documento |
TEXT | DEFAULT '' | Fecha del documento |
correo |
TEXT | DEFAULT '' | Email extraído por NER (ContactExtractor) |
cedula |
TEXT | DEFAULT '' | CC/CE/NIT extraído por NER |
hora_radicacion |
TEXT | DEFAULT '' | Hora de radicación (HH:MM:SS, auto) |
numero_acta |
TEXT | DEFAULT '' | Número de acta (~7 dígitos, manual) |
observaciones |
TEXT | DEFAULT '' | Notas y observaciones (texto libre) |
etiquetas |
TEXT | DEFAULT '' | Etiquetas JSON array |
direccion_demandante |
TEXT | DEFAULT '' | Dirección demandante (NER+manual) |
direccion_demandado |
TEXT | DEFAULT '' | Dirección demandado (NER+manual) |
secuencia_anterior |
TEXT | DEFAULT '' | Referencia a documento previo |
coordenada |
TEXT | DEFAULT '' | Coordenada geográfica |
has_provisional_measure |
INTEGER | DEFAULT 0 | 1 si se detecta medida provisional |
provisional_keywords |
TEXT | DEFAULT '' | JSON con keywords de medida provisional |
has_hechos |
INTEGER | DEFAULT 0 | 1 si se detecta sección de hechos |
has_pretensiones |
INTEGER | DEFAULT 0 | 1 si se detecta sección de pretensiones |
is_manual_entry |
INTEGER | DEFAULT 0 | 1 si fue ingreso manual (sin PDF) |
processing_cancelled_at |
TEXT | Timestamp si procesamiento cancelado | |
imported_at |
TEXT | DEFAULT '' | Timestamp de importación Excel (auditoría) |
created_at |
TEXT | NOT NULL | Timestamp de creación (ISO 8601) |
updated_at |
TEXT | NOT NULL | Timestamp de última actualización |
33 columnas (21 originales + 12 agregadas en Sprints 8-19)
Índices (6):
- idx_documents_hash en file_hash — Búsqueda rápida de duplicados (gate pre-OCR)
- idx_documents_status en status — Filtrado por estado
- idx_documents_type en document_type — Filtrado por tipo
- idx_documents_radicado en radicado — Búsqueda por radicado (import, CLI, GUI)
- idx_documents_cedula en cedula — Búsqueda por cédula (historial accionante)
- idx_documents_correo en correo — Búsqueda por correo (historial accionante)
2. documents_fts - Tabla Virtual FTS5¶
Tabla virtual para búsqueda full-text usando FTS5.
| Campo Indexado | Descripción |
|---|---|
content |
Texto completo del documento |
demandante |
Nombre del demandante |
demandado |
Nombre del demandado |
radicado |
Número de radicado |
juzgado |
Nombre del juzgado |
cedula |
CC/CE/NIT del accionante |
correo |
Email del accionante |
numero_acta |
Número de acta (buscable) |
observaciones |
Notas y observaciones |
Nota: direccion_demandante y direccion_demandado se almacenan en BD pero no se indexan en FTS5 (no son criterio de búsqueda útil).
Configuración FTS5 (9 campos):
CREATE VIRTUAL TABLE documents_fts USING fts5(
content,
demandante,
demandado,
radicado,
juzgado,
cedula,
correo,
numero_acta,
observaciones,
content='documents',
content_rowid='rowid'
);
Sincronización: Mediante triggers automáticos (INSERT, UPDATE, DELETE).
3. corrections - Correcciones de Usuario¶
Almacena el historial de correcciones para feedback loop y mejora del NER.
| Columna | Tipo | Restricción | Descripción |
|---|---|---|---|
id |
INTEGER | PK AUTOINCREMENT | ID secuencial |
document_id |
TEXT | FK → documents.id | Documento corregido |
field_name |
TEXT | NOT NULL | Campo corregible (ver lista abajo) |
original_value |
TEXT | Valor original del NER | |
corrected_value |
TEXT | Valor corregido por usuario | |
corrected_by |
TEXT | DEFAULT 'user' | Username autenticado (GOB-05) |
created_at |
TEXT | NOT NULL | Timestamp de corrección |
Índice: idx_corrections_document en document_id
Uso: Calcular accuracy del NER por campo, generar datos de entrenamiento.
4. processing_stats - Estadísticas de Procesamiento¶
Métricas de rendimiento del pipeline de procesamiento.
| Columna | Tipo | Restricción | Descripción |
|---|---|---|---|
id |
INTEGER | PK AUTOINCREMENT | ID secuencial |
document_id |
TEXT | FK → documents.id | Documento procesado |
ocr_engine |
TEXT | Motor: tesseract, paddleocr, native |
|
ocr_time_ms |
REAL | Tiempo de OCR en milisegundos (0 si native) | |
ner_time_ms |
REAL | Tiempo de NER en milisegundos | |
dedup_time_ms |
REAL | Tiempo de detección de duplicados en ms | |
total_time_ms |
REAL | Tiempo total del pipeline | |
pages_processed |
INTEGER | Número de páginas procesadas | |
file_size_bytes |
INTEGER | Tamaño del PDF en bytes | |
spacy_model_version |
TEXT | Versión del modelo SpaCy usado (GOB-07) | |
ocr_engine_version |
TEXT | Versión del motor OCR usado (GOB-07) | |
dedup_config_snapshot |
TEXT | JSON con configuración dedup (GOB-07) | |
created_at |
TEXT | NOT NULL | Timestamp del procesamiento |
Índice: idx_processing_stats_document en document_id
FK: document_id → documents.id ON DELETE CASCADE
5. logs - Logs de Aplicación¶
Almacena logs de la aplicación para auditoría, debugging y análisis.
| Columna | Tipo | Restricción | Descripción |
|---|---|---|---|
id |
INTEGER | PK AUTOINCREMENT | ID secuencial |
timestamp |
TEXT | NOT NULL | Timestamp del evento (ISO 8601) |
level |
TEXT | NOT NULL | Nivel: DEBUG, INFO, WARNING, ERROR, CRITICAL |
level_no |
INTEGER | NOT NULL | Nivel numérico (10=DEBUG, 50=CRITICAL) |
logger_name |
TEXT | NOT NULL | Nombre del logger (ej: SherlockDocs.ocr) |
module |
TEXT | Módulo Python de origen | |
func_name |
TEXT | Nombre de la función | |
line_no |
INTEGER | Número de línea del código | |
message |
TEXT | NOT NULL | Mensaje de log formateado |
exception |
TEXT | Stack trace si es una excepción | |
process_id |
INTEGER | PID del proceso | |
thread_id |
INTEGER | ID del thread | |
thread_name |
TEXT | Nombre del thread | |
created_at |
TEXT | NOT NULL | Timestamp de inserción en BD |
Índices:
- idx_logs_level en level - Filtrado por severidad
- idx_logs_timestamp en timestamp - Búsqueda temporal
- idx_logs_logger en logger_name - Filtrado por componente
Uso: Auditoría, debugging, análisis de errores, monitoreo de rendimiento.
6. audit_events - Eventos de Auditoría (GOB-06)¶
Registra acciones de usuario para trazabilidad y cumplimiento de gobernanza IA.
| Columna | Tipo | Restricción | Descripción |
|---|---|---|---|
id |
INTEGER | PK AUTOINCREMENT | ID secuencial |
user_id |
TEXT | NOT NULL | Usuario que ejecutó la acción (GOB-05 auth) |
action |
TEXT | NOT NULL | Acción: document_processed, document_corrected, etc. |
resource_type |
TEXT | NOT NULL | Tipo de recurso: document, import, export, session |
resource_id |
TEXT | ID del recurso afectado | |
details |
TEXT | JSON con detalles adicionales | |
ip_address |
TEXT | IP del cliente | |
created_at |
TEXT | NOT NULL | Timestamp del evento (ISO 8601) |
Índices (4):
- idx_audit_events_user en user_id — Filtrado por usuario
- idx_audit_events_action en action — Filtrado por tipo de acción
- idx_audit_events_resource en resource_type, resource_id — Búsqueda por recurso
- idx_audit_events_created en created_at — Búsqueda temporal
Uso: Trazabilidad GOB-06, reportes de auditoría GOB-11 (CLI audit-report), cumplimiento gobernanza IA.
Triggers de Sincronización FTS5¶
-- INSERT: Sincroniza nuevos documentos al índice FTS5
CREATE TRIGGER documents_ai AFTER INSERT ON documents BEGIN
INSERT INTO documents_fts(
rowid, content, demandante, demandado, radicado, juzgado,
cedula, correo, numero_acta, observaciones
)
VALUES (
NEW.rowid, NEW.content, NEW.demandante, NEW.demandado, NEW.radicado, NEW.juzgado,
NEW.cedula, NEW.correo, NEW.numero_acta, NEW.observaciones
);
END;
-- DELETE: Elimina del índice FTS5
CREATE TRIGGER documents_ad AFTER DELETE ON documents BEGIN
INSERT INTO documents_fts(
documents_fts, rowid, content, demandante, demandado, radicado, juzgado,
cedula, correo, numero_acta, observaciones
)
VALUES (
'delete', OLD.rowid, OLD.content, OLD.demandante, OLD.demandado, OLD.radicado, OLD.juzgado,
OLD.cedula, OLD.correo, OLD.numero_acta, OLD.observaciones
);
END;
-- UPDATE: Actualiza el índice FTS5 (delete + insert)
CREATE TRIGGER documents_au AFTER UPDATE ON documents BEGIN
INSERT INTO documents_fts(
documents_fts, rowid, content, demandante, demandado, radicado, juzgado,
cedula, correo, numero_acta, observaciones
)
VALUES (
'delete', OLD.rowid, OLD.content, OLD.demandante, OLD.demandado, OLD.radicado, OLD.juzgado,
OLD.cedula, OLD.correo, OLD.numero_acta, OLD.observaciones
);
INSERT INTO documents_fts(
rowid, content, demandante, demandado, radicado, juzgado,
cedula, correo, numero_acta, observaciones
)
VALUES (
NEW.rowid, NEW.content, NEW.demandante, NEW.demandado, NEW.radicado, NEW.juzgado,
NEW.cedula, NEW.correo, NEW.numero_acta, NEW.observaciones
);
END;
Campos corregibles: demandante, demandado, radicado, juzgado, fecha_documento, numero_acta, observaciones, etiquetas, direccion_demandante, direccion_demandado
Diagrama de Flujo de Datos¶
flowchart LR
subgraph Input["📄 Entrada"]
PDF[PDF Document]
end
subgraph Pipeline["⚙️ Pipeline"]
OCR[OCR Engine]
NER[NER Extractor]
Hash[SHA-256 Hash]
end
subgraph Storage["💾 Almacenamiento"]
Documents[(documents)]
FTS[(documents_fts)]
Stats[(processing_stats)]
Logs[(logs)]
AuditEvents[(audit_events)]
end
subgraph Feedback["🔄 Feedback Loop"]
User[Usuario]
Corrections[(corrections)]
end
subgraph Logging["📋 Logging"]
Logger[Logger Service]
end
PDF --> OCR
OCR --> NER
OCR --> Hash
NER --> Documents
Hash --> Documents
Documents -->|Triggers| FTS
OCR -->|Métricas| Stats
NER -->|Métricas| Stats
Documents --> User
User -->|Corrección| Corrections
Corrections -->|Actualiza| Documents
OCR -.->|Logs| Logger
NER -.->|Logs| Logger
Logger -->|Persiste| Logs
NER -->|Audit trail| AuditEvents
User -->|Corrección audit| AuditEvents
style Documents fill:#e8f5e9,stroke:#2e7d32
style FTS fill:#e3f2fd,stroke:#1565c0
style Corrections fill:#fff3e0,stroke:#ef6c00
style Stats fill:#f3e5f5,stroke:#7b1fa2
style Logs fill:#fce4ec,stroke:#c2185b
style AuditEvents fill:#fff8e1,stroke:#f9a825
Consultas Comunes¶
Búsqueda Full-Text (FTS5)¶
-- Búsqueda en todos los campos indexados
SELECT d.* FROM documents d
JOIN documents_fts fts ON d.rowid = fts.rowid
WHERE documents_fts MATCH 'término de búsqueda'
ORDER BY rank
LIMIT 10;
Búsqueda por Hash (Deduplicación)¶
Estadísticas de Correcciones¶
-- Correcciones por campo
SELECT field_name, COUNT(*) as count
FROM corrections
GROUP BY field_name;
-- Accuracy estimada por campo
SELECT field_name,
1.0 - (COUNT(*) * 1.0 / (SELECT COUNT(*) FROM documents)) as accuracy
FROM corrections
GROUP BY field_name;
Documentos por Estado¶
Consultas de Logs¶
-- Logs de errores recientes
SELECT * FROM logs
WHERE level IN ('ERROR', 'CRITICAL')
ORDER BY timestamp DESC
LIMIT 50;
-- Logs por componente
SELECT * FROM logs
WHERE logger_name LIKE 'SherlockDocs.ocr%'
ORDER BY timestamp DESC;
-- Conteo de errores por día
SELECT DATE(timestamp) as day, COUNT(*) as error_count
FROM logs
WHERE level = 'ERROR'
GROUP BY DATE(timestamp)
ORDER BY day DESC;
Consideraciones de Rendimiento¶
| Aspecto | Configuración | Impacto |
|---|---|---|
| Journal Mode | WAL | +50% lectura concurrente |
| Foreign Keys | ON | Integridad referencial |
| FTS5 | Tokenizer unicode61 | Soporte español completo |
| Índices | 6 en documents, 1 en corrections, 1 en processing_stats, 3 en logs, 4 en audit_events | Búsquedas O(log n) |
Migración a PostgreSQL (Futuro)¶
El esquema está diseñado para facilitar migración:
| SQLite | PostgreSQL |
|---|---|
TEXT |
VARCHAR / TEXT |
REAL |
FLOAT / DECIMAL |
INTEGER AUTOINCREMENT |
SERIAL |
| FTS5 | tsvector + GIN index |
| Triggers | Triggers (sintaxis similar) |
Última actualización: 2026-03-06 (GOB-05 auth + GOB-06 audit_events + GOB-07 cols + GOB-11 audit-report)