2026-08-07 — marvelousdb: migracion a SQLite completo (FTS5)
Contexto: el usuario pidio unificar los personajes en una base .sqlite para “mejor consumo y portabilidad”. Se eligio la opcion SQLite completo con FTS5.
Decisiones
- Motor:
node:sqlite(DatabaseSync) de Node >= 23.4 — cero dependencias nativas. SQLite 3.50.4. Warning experimental silenciado con--disable-warning=ExperimentalWarningen los npm scripts. - Esquema (
data/build-sqlite.js):characters(id, name, subtitle, thumbnail, gender, universe, data)— data es el JSON completo; name/subtitle/gender/universe son columnas indexadas.comics(id, title, subtitle, thumbnail, data).- FTS5 virtual tables
characters_ftsycomics_ftscon tokenizer trigram (substring matching, case-insensitive) +bm25()ranking.
- Búsqueda: MATCH con frases por token (3+ chars; trigram no matchea
queries cortas → fallback LIKE sobre name/title).
fieldse mapea a columnas FTS (wiki.real_name→ real_name OR aliases). Filtros gender/universe por SQL con bind. Nada en memoria. - Build:
npm run build:sqlite(o auto-build en primer arranque de la API). Escanea data/ y data/pdsh/..dben .gitignore (reconstruible). - Dependencias: eliminado FlexSearch (ya no se usa).
Resultados
- .db: 10,819 personajes + 30,179 comics, 268.9 MB (vs 361 MB JSON), build en 11.1s.
- Arranque API: 0.5s (antes ~7s indexando 40k JSON). RSS: 66 MB (antes ~500 MB).
- 15/15 tests verdes (misma firma de API; el test child ya no necesita DATA_DIR, el .db contiene ambos datasets).
- Todas las rutas 200 (home, /vs, búsquedas, detalles).
Bugs encontrados
- “column index out of range”:
bind()metia limit/offset en params Y se pasaban sueltos → doble. Fix: LIMIT/OFFSET con ’?’ literal. - “no such column: issueNumber”: la tabla comics no tiene esa columna (está en el JSON). Fix: quitar del SELECT del listado; el detail la lee del JSON.
- “ambiguous column name: universe”: characters_fts comparte nombre de columna
→ calificar filtros con
c.en los JOINs. - thumbnails null en comic detail: mismatch Number/String en Map keys → normalizar a String.
Pendientes
- Si el .db crece mucho: external-content FTS o trigram solo en campos relevantes.
- El usuario tiene el proceso viejo corriendo; reiniciar npm start para ver SQLite.