Sobre Full Text Searchs

PlayingDead

Antes de nada: si has visto este post en Forocoches que no te explote la cabeza, soy yo mismo, creo que aquí hay gente con más conocimiento técnico...

Hola mediavideros.

Nunca he realizado Full Text Searchs sobre una DB y me estoy planteando hacerlo, y me surge alguna duda.

Imaginemos que lo que quiero hacer es un buscador parametrizado, ya que cada fila de la tabla principal tiene unas relaciones en una base de datos normalizada, y me interesa poder hacer distintos filtros. Entonces, ¿cómo podría conjuntarse eso con la búsqueda de texto completo?

He pensado en que, teóricamente, habría dos escenarios:

1 Si el usuario introduce texto en la caja de búsqueda y no introduce parámetros, simplemente realizar la búsqueda de texto completo y arrojar los resultados.

2 Si el usuario introduce texto en la caja de búsqueda y establece parámetros, primero realizar la búsqueda de texto completo sin límite de filas y hacer los filtros sobre ese conjunto de resultados con los parámetros que ha pasado el usuario, estableciendo posteriormente el límite de filas de ese último conjunto.

Son los dos escenarios que se me ocurren. ¿Me estoy comiendo mucho la cabeza o hay algo más simple?

Traber

SI lo que vas a hacer es algo basado en un motor de búsqueda, ¿te has planteado usar algo tipo Elasticsearch? Lo de usar parámetros en ES está chupado, pero en MySQL a lo mejor es complicarte mucho.

1 respuesta
PlayingDead

#2 Y qué tal lleva Elastic Search el manejar relaciones de una bd relacional?... Porque las búsquedas parametrizadas son basadas en muchas relaciones

O mejor preguntado... Puedo pasarle la consulta sql que devuelve todos los datos que quiero en base a los parámetros a ES y que a partir de eso haga una búsqueda fullsearch?

2 respuestas
Traber

#3 En Elasticsearch básicamente, no hay tablas, ni relaciones, lo que serían las "filas" se consideran "documentos", y todos los documentos se almacenan al mismo nivel (como en una misma tabla). Toda la información de los documentos está contenida dentro de los propios documentos, de manera que si vendes televisiones, cada tele tendría sus campos tipo "tamaño", "resolución", "smart_tv", etc... Ejemplo:

Alerta: Los documentos en ES se definen en JSON, si no estás acostumbrado al formato, ve pillando SIDA -

{
    "nombre": "Sharp 1488K 49",
    "marca": "Sharp",
    "pulgadas": "49",
    "resolución": [
        "4K", 
        "3840x2160"
    ],
    "smart_tv": false
}

Y para buscarla, la query sería algo así:

{
    "query": {
        "bool" : {
            "must": {
                "term": {
                    "pulgadas": "49"
                }
            },
            "should": {
                "multi_match" : {
                    "query" : "texto arbitrario introducido por el usuario",
                    "fields" : [ 
                        "campos en los",
                        "que quieras buscar",
                        "o '*' para buscar en todos",
                        "*"
                    ] 
                }
            },
            "minimum_should_match" : 1
        }
    }
}

No hay relaciones como tal, pero no creo que las necesites, y menos para filtrar por parámetros. Para ello, se utilizan las agregaciones, o aggregations; y es más, ya te hace tareas el propio Elasticsearch como agruparte, aparte del conjunto de resultados actual, cuántos resultados tendrías si aplicas X filtro a la búsqueda que ya tienes. Te recomiendo ver la documentación porque si lo que vas a hacer se basa fuertemente en la búsqueda, no hay nada igual (y es gratis).

1 respuesta
Yumigestor

Hola, yo en nuestro proyecto, las búsquedas full text las hago sobre un servidor con Elasticsearch y en paralelo sobre Mysql en otra máquina la query relacional.
Cuando tengo los 2 resultados, hago una interseccion de array y ese es el resultado final.

A continuación guardo con memcached la lista completa final de claves únicas resultante de la interseccion y sobre esa interseccion corto según la paginacion.

Si te interesa te puedo enseñar como funciona y darte más detalles.

1 respuesta
PlayingDead

#5 entiendo el funcionamiento que planteas, cruzas los dos arrays y te quedas solo con las ids que te interesan del sql que hace las relaciones no??

Muchas gracias, te enviaré un mensaje

PlayingDead

#4 humm.. estoy pensando que podría hacer la búsqueda fullsearch con mysql, tiene su implementación

Yumigestor

El full search de mysql funciona muy mal comparado con Elasticsearch

JuAn4k4

Depende del número de registros que estemos hablando.
Igual el fts de MySQL te vale... aunque la mejor opción es un ES en el que sacas los resultados, y luego los mapeas o extiendes con datos de la db si realmente hacen falta o estás haciendo backend for fronted o similar

1 respuesta
PlayingDead

#9 175.000 registros

1 respuesta
JuAn4k4

#10 Te sobra con mysql, aunque también depende del tamaño de cada uno, no vayan a ser Gb de texto cada registro

1 respuesta
PlayingDead

#11 muy pequeño el tamaño por registro. Gracias por tu ayuda. :)

1
B

#3 Mal, las relaciones ya las lleva mal.

Yo tenía un comparador de precio en Elasticsearch...nuestros productos un índice, los suyos otro. Total, que la relación de, que competidor tiene un precio más barato había que precalcularla, y eran 4 campos por dominio.

Ahora, no hay bicho más rápido que Elastic, tanto en escritura como en lectura. Ahora mismo tenemos 35 millones de registros de Lectura de la luz y el tío se toca los cojones basto.

Siempre y cuando puedas "aplanar" el objeto, Elastic va a ser ultra rápido.

Lo peor que tiene? La falta de clientes, el cliente de Php está MUY pelado, que entiendo que esa era la intención, pero joder. Yo al final acabe creando una librería pequeña para poder manejar objetos sin reventarme la crisma, aunque tengo todavía que hacer un sistema de consultas.

Ahora, si te vale con mysql es matar moscas a cañonazos, Elastic es rápido, pero chupa ram, si te puedes ahorrar un servicio mejor.

Si quieres experimentar con el y que sea práctico, mirate los agentes que tiene para sacar métricas y logs, es demencial

Usuarios habituales