Cuando empecé a construir la búsqueda de notas para NotasMD, mi primer
instinto fue reservar tiempo para integrar Elasticsearch o Algolia. Pero con menos de un millón
de filas, Postgres ya trae todo lo necesario: tsvector, tsquery e índices GIN.
El problema con LIKE '%query%'
Un LIKE con comodines a ambos lados no puede usar un índice B-tree normal, así que Postgres
termina escaneando la tabla completa. Funciona con 100 filas, pero se degrada rápido.
Columna generada + índice GIN
La solución es agregar una columna tsvector generada automáticamente a partir del contenido,
y luego indexarla con GIN:
Con eso, una búsqueda pasa de escanear filas a resolver contra un índice:
ts_rank para relevancia
ts_rank pondera por frecuencia y posición de las coincidencias, así que resultados donde el
término aparece en el título suben antes que los que solo lo mencionan una vez en el cuerpo.
No es tan sofisticado como BM25, pero para búsqueda dentro de notas personales es más que
suficiente.
Cuándo sí vale la pena algo externo
Si necesitas facetas, typo-tolerance agresivo, o buscar sobre decenas de millones de
documentos con baja latencia garantizada, Elasticsearch o Meilisearch siguen siendo la mejor
opción. Pero para la mayoría de productos internos o MVPs, tsvector evita una pieza más de
infraestructura que mantener.