Pregunta

Tengo un problema de desarrollo de aplicaciones web para el cual desarrollé una solución, pero estoy tratando de encontrar otras ideas que puedan solucionar algunos problemas de rendimiento que estoy viendo.

planteamiento del problema:

  • un usuario ingresa varias palabras clave/tokens
  • la aplicación busca coincidencias con los tokens
  • necesito un resultado para cada token
    • es decir, si una entrada tiene 3 tokens, necesito la identificación de la entrada 3 veces
  • clasificar los resultados
    • asignar X puntos por coincidencia de tokens
    • ordenar los identificadores de entrada según los puntos
    • Si los valores de puntos son los mismos, use la fecha para ordenar los resultados.

Lo que quiero poder hacer, pero no lo he descubierto, es enviar 1 consulta que devuelva algo similar a los resultados de in(), pero devuelva una identificación de entrada duplicada para cada coincidencia de token para cada identificación de entrada verificada.

¿Existe una mejor manera de hacer esto que la que estoy haciendo, usando múltiples consultas individuales ejecutando una consulta por token?Si es así, ¿cuál es la forma más sencilla de implementarlos?

editar
Ya he tokenizado las entradas, por lo que, por ejemplo, "ver ejecución puntual" tiene un ID de entrada de 1 y tres tokens, "ver", "spot", "ejecutar", y esos están en una tabla de tokens separada. con identificadores de entrada relevantes para ellos, por lo que la tabla podría verse así:

'see', 1 
'spot', 1 
'run', 1 
'run', 2 
'spot', 3 
¿Fue útil?

Solución

podría lograr esto en una consulta usando 'UNION ALL' en MySQL.

Simplemente recorra los tokens en PHP creando una UNION ALL para cada token:

por ejemplo, si los tokens son 'x', 'y' y 'z', su consulta puede verse así

SELECT * FROM `entries` 
WHERE token like "%x%" union all 
    SELECT * FROM `entries` 
    WHERE token like "%y%" union all 
        SELECT * FROM `entries` 
        WHERE token like "%z%" ORDER BY score ect...

La cláusula de orden debe operar en todo el conjunto de resultados como uno solo, que es lo que necesita.

En términos de rendimiento, no será tan rápido (supongo), sin embargo, con las bases de datos, la principal sobrecarga en términos de velocidad suele ser enviar la consulta al motor de la base de datos desde PHP y recibir los resultados.Con esta técnica, esto solo ocurre una vez en lugar de una vez por token, por lo que el rendimiento aumentará, pero no sé si será suficiente.

Otros consejos

Sé que esto no es estrictamente una respuesta a la pregunta que haces. pero si su tabla tiene miles en lugar de millones de filas, entonces una solución FULLTEXT podría ser la mejor manera de hacerlo.

En MySQL, cuando usa MATCH en su columna indexada, a cada palabra clave que proporcione se le asignará una puntuación de relevancia (calculada aproximadamente por la cantidad de veces que se mencionó cada palabra clave) que será más precisa que su método y ciertamente más eficiente para múltiples palabras clave.

Mira aquí:http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html

Si está utilizando el patrón UNION ALL, es posible que también desee incluir las siguientes partes en su consulta:

SELECT COUNT(*) AS C
...
GROUP BY ID
ORDER BY c DESC

Si bien este es un ejemplo realmente trivial, le proporciona la frecuencia de las coincidencias para cada resultado y, para empezar, esto podría ser una pseudoclasificación.

Probablemente obtendrá un rendimiento mucho mejor si utiliza una estructura de datos diseñada para tareas de búsqueda en lugar de una base de datos.Por ejemplo, podrías intentar construir un índice invertido.Sin embargo, en lugar de escribirlo usted mismo, es posible que también desee buscar algo como Lucena que hace la mayor parte del trabajo por usted.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top