9 puntos por GN⁺ 2025-11-18 | 1 comentarios | Compartir por WhatsApp
  • Implementa una arquitectura de motor de búsqueda que funciona sin servicios externos usando la base de datos existente, con enfoque en tokenización, pesos y scoring
  • La idea central es tokenizar y almacenar todo el texto, y al buscar hacer coincidir los tokens del mismo modo para calcular la relevancia
  • Combina tokenizadores Word, Prefix y N-Gram para cubrir coincidencia exacta, coincidencia parcial y tolerancia a errores tipográficos; cada tokenizador tiene su propio peso
  • Mediante un sistema de pesos y un algoritmo de scoring basado en SQL, evalúa en conjunto la longitud del documento, la diversidad de tokens y la calidad promedio
  • Tiene alta escalabilidad y transparencia, por lo que permite agregar nuevos tokenizadores o tipos de documento, ajustar pesos y modificar el scoring con libertad

Por qué crear tu propio motor de búsqueda

  • Los servicios externos como Elasticsearch o Algolia son potentes, pero implican la carga de aprender APIs complejas y gestionar infraestructura
  • Cuando solo se necesita una función de búsqueda que se integre con la base de datos existente y sea fácil de depurar, construirla directamente puede ser útil
  • El objetivo es un motor de búsqueda simple que devuelva resultados relevantes sin dependencias externas

Concepto clave: tokenización y matching

  • El principio básico es tokenizar todo el texto y almacenarlo, y al buscar generar tokens del mismo modo para hacer matching
  • En la fase de indexación, el contenido se divide en tokens y se guarda junto con sus pesos
  • En la fase de búsqueda, la consulta se tokeniza de la misma manera para encontrar tokens coincidentes y calcular la puntuación
  • En la fase de scoring, se usan los pesos almacenados para obtener la puntuación de relevancia

Diseño del esquema de base de datos

  • Se usan dos tablas: index_tokens e index_entries
    • index_tokens: almacena tokens únicos y pesos por tokenizador
    • index_entries: conecta tokens con documentos y guarda la puntuación final reflejando pesos de campo, documento y tokenizador
  • Fórmula de cálculo del peso final:
    field_weight × tokenizer_weight × ceil(sqrt(token_length))
  • Los índices se configuran para consulta de documentos, consulta de tokens, queries por campo y filtrado por peso

Sistema de tokenización

  • WordTokenizer: separación por palabra, eliminación de palabras cortas, para coincidencia exacta (peso 20)
  • PrefixTokenizer: genera prefijos de palabras, para autocompletado y coincidencia parcial (peso 5)
  • NGramsTokenizer: genera combinaciones de caracteres de longitud fija, para errores tipográficos y coincidencia parcial (peso 1)
  • Todos los tokenizadores realizan en común conversión a minúsculas, eliminación de caracteres especiales y normalización de espacios

Sistema de pesos

  • Peso de campo: refleja la importancia de título, cuerpo, palabras clave, etc.
  • Peso del tokenizador: Word > Prefix > N-Gram
  • Peso del documento: se calcula combinando los dos elementos anteriores con la longitud del token
  • Se usa la función ceil(sqrt()) para suavizar el impacto de tokens largos, y si hace falta puede ajustarse con una función logarítmica o lineal

Servicio de indexación

  • Solo se pueden indexar documentos que implementen IndexableDocumentInterface
  • Al crear o modificar un documento, la indexación se ejecuta mediante un listener de eventos o comandos (app:index-document, app:reindex-documents)
  • Procedimiento:
    • Eliminar el índice existente y luego generar nuevos tokens
    • Ejecutar todos los tokenizadores para cada campo
    • Verificar si el token existe y crearlo si no (findOrCreateToken)
    • Hacer inserción por lotes (batch insert) en index_entries con el peso calculado
  • Estructura pensada para evitar duplicados, mejorar el rendimiento y responder a actualizaciones

Servicio de búsqueda

  • Procesa la consulta con los mismos tokenizadores para obtener el mismo conjunto de tokens que en la indexación
  • Elimina tokens duplicados, los ordena por longitud (priorizando los más largos) y los limita a un máximo de 300
  • Mediante una query SQL une tokens y documentos, y calcula y ordena la puntuación de relevancia
  • Devuelve los resultados con la forma SearchResult(documentId, score)

Algoritmo de scoring

  • Puntuación base: SUM(sd.weight)
  • Ajuste por diversidad de tokens: LOG(1 + COUNT(DISTINCT token_id))
  • Ajuste por peso promedio: LOG(1 + AVG(weight))
  • Penalización por longitud del documento: 1 / (1 + LOG(1 + token_count))
  • Normalización: se divide por la puntuación máxima para ajustarlo al rango 0~1
  • El filtro de peso mínimo de token (st2.weight >= ?) permite eliminar coincidencias irrelevantes de muy bajo peso

Procesamiento de resultados

  • Los resultados de búsqueda se devuelven como ID de documento y puntuación, y se convierten en documentos reales a través del repositorio (repository)
  • Se usa la función FIELD() para consultar los documentos manteniendo el orden de los resultados de búsqueda

Escalabilidad del sistema

  • Se pueden agregar nuevos tokenizadores implementando TokenizerInterface
  • Se pueden registrar nuevos tipos de documento implementando IndexableDocumentInterface
  • La lógica de pesos o scoring puede ajustarse solo modificando SQL

Conclusión

  • Esta estructura es un motor de búsqueda simple pero realmente funcional, que ofrece rendimiento suficiente sin infraestructura externa
  • Sus ventajas son la lógica clara, el control total y la facilidad para depurar
  • Se enfatiza que, más que un sistema complejo, el código que puedes entender y controlar directamente puede tener más valor

1 comentarios

 
GN⁺ 2025-11-18
Opinión de Hacker News
  • La idea básica de la búsqueda es simple y es un campo de problemas interesante
    Pero lo realmente difícil es manejar grandes volúmenes de datos y procesar consultas ambiguas
    Un enfoque basado en DBMS puede estar bien para un sitio web pequeño, pero al escalar al tamaño de la Wikipedia en inglés, llega rápido a su límite
    Como introducción, el e-book de SeIRP es un buen recurso gratuito

    • Los datos a gran escala son obviamente difíciles, pero creo que lidiar con consultas ambiguas es un subproblema de “cómo decidir cuáles son los resultados más relevantes”
      El hecho de que no haya una respuesta clara lo hace especialmente complicado
      Google a veces muestra anuncios como si fueran ‘los resultados más relevantes’, así que Marginalia Search es un buen caso de contraste
      Me pregunto si has revisado los papers de TREC
    • Hoy en día, creo que un problema todavía mayor es evitar el spam de SEO
      Los motores de búsqueda tienen que pelear constantemente contra actores adversariales que buscan ingresos por publicidad
      Se vuelve un juego interminable del gato y el ratón en el que hay que cambiar continuamente las métricas de calidad para que no puedan explotarlas
    • Si uno operara procesos de negocio centrados en texto con SQLite en un solo servidor (de unos mil dólares), me da curiosidad saber cuál sería en la práctica la escala del repositorio de documentos que se podría manejar
      Quisiera saber qué tamaño de corpus se podría buscar tomando como referencia una velocidad de 5 segundos por consulta y unas 12 consultas por minuto
    • Me encanta Marginalia Search
    • Creo que la dificultad de la búsqueda no está solo en el tamaño de los datos, sino en decidir qué resultados devolver
      Por ejemplo, es difícil juzgar cuál sería un resultado “mejor”: el artículo wiki de Gilligan’s Island o un blog de fans
      Si además se suma la manipulación del ranking o el keyword stuffing, se vuelve un reto mucho más complejo que un simple problema de escalabilidad
  • La búsqueda es realmente difícil
    Incluso empresas con enormes recursos y capacidad técnica como Apple, Microsoft y OpenAI tienen baja calidad en sus funciones de búsqueda
    Esto no es solo un problema técnico

    • La razón por la que la mayoría de las empresas no implementan bien la búsqueda es que la cultura corporativa y la forma de desarrollo chocan con el desarrollo de motores de búsqueda
      Para mejorar la calidad de búsqueda hay que ajustar con mucho detalle los parámetros de ranking, y ese tipo de trabajo es difícil de planificar con sistemas de gestión como sprints o Jira
      Al final, es un área donde hace falta confianza y autonomía para los desarrolladores
    • Pero en algunas empresas la mala calidad se debe simplemente a que la búsqueda no es una prioridad
      Invierten miles de millones en modelos de IA, pero la webapp o la búsqueda quedan como algo secundario, y por eso salen esos resultados
  • Hace unos 10 años trabajé con un colega que hacía el doctorado en diseño de motores de búsqueda
    Hablaba con muchísima pasión sobre la integración entre búsqueda y bases de datos, y aprendí bastante gracias a eso
    Algún día me gustaría explorar a fondo el funcionamiento interno de Apache Solr y Lucene

    • A mí también me encanta hablar durante horas de mi área, pero no hay tanta gente interesada en la implementación detallada de sistemas grandes
  • Antes no había soluciones de búsqueda open source, así que había que construirlas uno mismo
    La lección que dejó esa experiencia fue: “no construyas tu propio motor de búsqueda
    Muchísima gente ha dedicado años a este problema, y si lo haces por tu cuenta, caes en un infierno interminable de mantenimiento
    En cuanto empiezan los pedidos de “agreguen corrección de errores tipográficos” o “el próximo año metamos también una taxonomía”, ya no se termina nunca

  • Disfruté muchísimo un curso del profesor David Evans de la University of Virginia sobre cómo construir un motor de búsqueda
    Construir directamente un “motor de búsqueda clásico” fue un proyecto muy divertido
    Se puede consultar el enlace del curso y la lista de reproducción en YouTube

    • Yo también tomé ese curso, y fue una clase interesante y muy sustanciosa incluso para programadores principiantes
  • Me molesta que los motores de búsqueda que uso con frecuencia ignoren siglas o palabras de 2 o 3 letras
    Es realmente incómodo cuando eliminan palabras cortas como “mp3” o “PHP” al buscarlas

  • Leí Programming Collective Intelligence de Toby Segaran y me inspiró con muchas ideas sobre búsqueda, recomendación y clasificadores, entre otras cosas

    • A mí también me gustó ese libro, pero luego vi al autor decir en YouTube que “ya está desactualizado, así que no lo usen”
    • Era un libro realmente bueno; me pregunto si habrá una edición actualizada equivalente para 2025
  • Fue un artículo interesante
    Me da curiosidad qué tan alto será el nivel de optimización de tokenizadores que usan los motores de búsqueda populares

  • Me pregunto qué tan escalable será este sistema
    Elasticsearch muestra un rendimiento bastante impresionante incluso más allá de la escala recomendada

  • No es tan difícil crear un motor de búsqueda de texto simple
    Pero crear un buen motor de búsqueda es una historia completamente distinta
    No basta con implementar un algoritmo como BM25
    La mayoría de las empresas a las que he asesorado terminan migrando de su solución propia a Elasticsearch u Opensearch
    Una implementación propia parece simple al principio, pero con el tiempo se vuelve compleja por los problemas de ranking y la degradación del rendimiento
    Se repiten síntomas como “es lento” o “arroja resultados absurdos”
    Elasticsearch ya viene resolviendo estos problemas desde hace 10 años, y ahora está mucho más avanzado
    Se dice que “es difícil de configurar”, pero hoy en día casi todo se configura automáticamente, y además hay muchos servicios administrados
    Incluso es más fácil de manejar que Postgres
    Al final, lo importante es optimizar el mapeo del índice
    Hay gente que dice “no necesitamos esas funciones avanzadas”, pero en la práctica la calidad de búsqueda está directamente ligada a la supervivencia del negocio
    Si de verdad quieres una búsqueda bien hecha, al final tienes que aceptar esa complejidad

    • Yo también uso Elasticsearch por defecto
      También se ven interesantes alternativas emergentes como SeekStorm, que últimamente aparece mucho en HN, aunque todavía no he visto casos reales en producción
    • Coincido con eso de que “no hay funciones innecesarias”
      En especial, fue útil el consejo de desactivar el dynamic mapping y evitar indexar campos innecesarios
    • Me pregunto qué opinan de ManticoreSearch
      Tengo entendido que es un proyecto más antiguo que Lucene