BUSQUEDA.md 5.38 KB

Lógica del Buscador

Resumen

Buscador instantáneo con Fuse.js en cliente. Busca en clasificadores presupuestarios y navega a vistas de detalle.

Decisiones de Diseño

Motor de búsqueda

  • Tecnología: Fuse.js (cliente)
  • Razón: ~2,000-4,000 registros totales, cabe en memoria, búsqueda instantánea sin latencia

Tolerancia a errores

  • Normalización de acentos ("andres" → "andrés")
  • Case-insensitive ("UMSA" = "umsa")
  • Fuzzy matching ("univercidad" → "universidad")

Comportamiento

Parámetro Valor
Debounce 200-300ms
Mínimo caracteres 2
Máximo resultados 10-30
Navegación Flechas ↑↓ + Enter + scroll de mouse y loq ue corresponda para mobiles

Estructura del Índice

Índice unificado (futuro)

Todos los clasificadores en un solo array con tipo:

// src/lib/data/index.js
const indice = [
  {
    tipo: 'entidad',
    codigo: 139,
    nombre: 'Universidad Mayor De San Andrés',
    sigla: 'UMSA',
    contexto: 'Universidades Públicas',
    años: 20,
    // campos normalizados para búsqueda
    _nombre_normalizado: 'universidad mayor de san andres',
    _sigla_normalizada: 'umsa'
  },
  {
    tipo: 'objeto_gasto',
    codigo: 25100,
    nombre: 'Pasajes',
    contexto: 'Servicios',
    // ...
  }
]

Por ahora (MVP)

Solo clasificador de entidades (clas_institucional).

Columnas de Búsqueda

Entidades (clas_institucional)

Columna Buscar Mostrar
desc_entidad ✓ nombre principal
sigla_entidad ✓ entre paréntesis
desc_area ✓ contexto
n_gestiones ✓ "X años de datos"
entidad para URL

Objetos de gasto (futuro)

Columna Buscar Mostrar
desc_objeto ✓ nombre principal
codigo_objeto ✓ código
desc_partida ✓ contexto

Flujo de Búsqueda

1. CARGA INICIAL
   App monta → descarga clasificadores → construye índice Fuse.js

2. USUARIO ESCRIBE
   Input → debounce 250ms → si ≥2 chars → Fuse.search()

3. RESULTADOS
   Fuse devuelve matches → renderizar lista con highlighting

4. SELECCIÓN
   Click o Enter → navegar a /entidad/[codigo] o /gasto/[codigo]

Estructura de URLs

/entidad/[codigo]     →  /entidad/139
/gasto/[codigo]       →  /gasto/25100  (futuro)
/area/[codigo]        →  /area/1.1.4   (futuro, opcional)

Formato de Resultados

┌─────────────────────────────────────────────────────┐
│ 🔍 [buscar entidad, objeto de gasto...]            │
├─────────────────────────────────────────────────────┤
│ Universidad Mayor De San Andrés (UMSA)              │
│ Universidades Públicas · 20 años                    │
├─────────────────────────────────────────────────────┤
│ Universidad Pública De El Alto (UPEA)               │
│ Universidades Públicas · 21 años                    │
├─────────────────────────────────────────────────────┤
│ ...                                                 │
└─────────────────────────────────────────────────────┘

Estados del Buscador

Estado Qué mostrar
Vacío (< 2 chars) Placeholder o sugerencias
Cargando índice Spinner / "Cargando..."
Buscando Nada (es instantáneo)
Con resultados Lista de resultados
Sin resultados "No se encontraron resultados para 'xyz'"
Error "Error al cargar datos"

Estructura de Archivos

src/lib/
├── components/
│   └── search/
│       ├── SearchBox.svelte       ← Input + lógica de búsqueda
│       ├── SearchResults.svelte   ← Lista de resultados
│       └── SearchResultItem.svelte ← Item individual
├── services/
│   ├── supabase.js               ← Cliente Supabase
│   └── search.js                 ← Inicialización Fuse.js
├── stores/
│   └── searchStore.js            ← Estado: query, results, loading
├── utils/
│   └── normalize.js              ← Normalización de texto
└── data/
    └── index.js                  ← Carga y construcción del índice

Trabajo Futuro

Índice normalizado

Cuando haya múltiples clasificadores, crear un proceso que:

  1. Descargue todos los clasificadores
  2. Normalice campos de búsqueda (acentos, minúsculas)
  3. Genere un índice unificado optimizado
  4. Posiblemente pre-computar en servidor y servir como JSON estático

Migración a servidor

Si el índice supera ~20,000 registros:

  1. Habilitar extensión pg_trgm en PostgreSQL
  2. Crear índices GIN en columnas de búsqueda
  3. Cambiar de Fuse.js a queries con similarity() o % operator
  4. El componente de UI se mantiene igual, solo cambia el servicio

Documento de referencia para la implementación del buscador