Foros del Web » Programación para mayores de 30 ;) » Bases de Datos General » Mysql »

[SOLUCIONADO] Buscador de música

Estas en el tema de Buscador de música en el foro de Mysql en Foros del Web. Hola, no soy exactamente duro en MySQL y me convencí de eso con solamente ver unos cuantos post en este foro (confieso que no había ...
  #1 (permalink)  
Antiguo 20/04/2014, 01:05
 
Fecha de Ingreso: abril-2014
Mensajes: 72
Antigüedad: 10 años
Puntos: 5
Buscador de música

Hola, no soy exactamente duro en MySQL y me convencí de eso con solamente ver unos cuantos post en este foro (confieso que no había leído en este sub foro nunca). Así que vine en busca del buen consejo de los que saben.

Estoy haciendo una web de música y me toca trabajar con el buscador, anteriormente tenía una función PHP que me creaba una sentencia con MATCH... AGAINST... y ponía LIKE a las palabras de menos de tres letras, para buscar en el nombre de los artistas y de las canciones. Todo eso lo resolvía en una sola mega función.

Ahora bien, he modificado la tabla para permitir Featurings (cuando dos cantantes que normalmente no cantan juntos hacen una canción juntos Ej.: Wisin y Yandel FT. Ricardo Montaner) y quería ver como hacía otra super-mega-ultra-consulta que me saque del apuro... pero andando por el foro me encontré con un comentario del cual cito la parte interesante para mí:
Cita:
Iniciado por gnzsoloyo Ver Mensaje
Lo que no se recomienda jamás es hacer un "buscatodo en todo", por más que parezca una buena idea. Hacer 5 queries consecutivas puede ser más eficiente qmue una "superconsulta" que lo busque todo.
Cómo me recomendarían resolver el asunto ahora que la función se haría más compleja al ponerlo a buscar en aun más tablas?

Básicamente, la parte relevante de la estructura de mi base de datos es:

Tabla: artistas
Campos: id, nombre

Tabla: cancion
Campos: id, nombre_cancion, id_del_artista

Tabla: featuring
Campos: id, id_de_la _cancion, id_del artista

------------------

En el ejemplo del Featuring de de Wisin y Yandel con Ricardo Montaner, los datos serían así:

artistas
id(1), nombre(Ricardo Montaner)
id(2), nombre(Wisin y Yandel)

cancion
id(1), nombre_cancion(Donde está el Amor), id_del_artista(1)

featuring
id(1), id_de_la _cancion(1), id_del artista(2)

-------------

Bueno, intenté explicarme lo mejor posible a pesar de no conocer la correcta de plasmar por escrito la estructura de mi base de datos. Espero no se hayan perdido y me puedan ayudar. Recuerden: La duda es ¿Cómo hago un motor de búsqueda lo más eficiente posible?

Última edición por zyxer; 20/04/2014 a las 01:12
  #2 (permalink)  
Antiguo 20/04/2014, 07:57
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 4 meses
Puntos: 2658
Respuesta: Buscador de música

Personalmente yo resolveria tu problema analizando tu modelo de datos necesario de otra forma, que facilitaría todas las consultas.
Mirémoslo así:
- Una canción puede tener 1 o N autores.
- Un autor puede serlo de 1 o N canciones.
- Una canción puede haber sido interpretada por 1 o N artistas.
- Una canción puede haber sido editada por 1 o N sellos y en 1 o N volúmenes (CDs, por caso)

¿Qué implica eso?
Que tienes este esquema de tablas:

CANCION(idCancion, nombreCancion)
AUTOR(IdAutor, NombreAutor, ...otros datos)
CANTANTE(IdArtista, NombreArtista, ...otros datos)
CANCION_AUTOR(idcancion, idAutor)
CANCION_INTERPRETE(idCancion, idArtista)

Mas o menos esa es la idea.

El concepto es simple: Primero, si puedes tener al menos una canción que tenga más de un autor, o más de un intérprete, ya no puedes relacionar la canción con ellos dentro de la tabla de la canción porque tienes una relación N:M, que obligatoriamente se debe crear.
Además, si puede ser editada en diferentes sellos, y en cada sello con un artista distinto, requiere un modelado mas preciso, que abarque esas condiciones.

En cualquier caso, relacionar las canciones con sus interpretes y/o sus autores por medio de una tabla relacional te facilita la tarea de realizar una consulta de búsqueda sin complicaciones, porque siempre estarías haciendo la query sobre un único campo de una tabla, o por sólo algunos de ellos.
En el contexto descripto, es posible crear indices útiles, sean o no FULLTEXT.

Finalmente, algunas recomendaciones para que tengas cuentas en los LIKE:
1) No es buena idea hacer búsquedas por palabras de menos de cinco letras, porque las coincidencias (falsas en su mayoría) son demasiadas. MySQL no implementó ese límite para el MATCH() AGAINST() porque si. Es porque es total y absolutamente ineficiente.
Supongamos esto: ¿Cuántas coincidencias inútiles podría darte bsucar nombres que contengan "del", "sit", "abs", "llo" o cosas así?
Lo que se hace normalmente es crear en los formularios una restricción para que no se pueda enviar a hacer la búsqueda a menos que el el textbox contenga por lo menos una cantidad X de caracteres no sin espacios en blanco.
2) Hacer busquedas con LIKE con una palabra entre dos comodines es total y absolutamente ineficiente, porque le pides todo lo que comience con cualquier cosa y termine con cualquier cosa. En esencia, obliga a leer toda la tabla.
¿Esto último te parece bueno?
No, por eso no se recomienda.

Espero que estos detalles te sirvan
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)

Última edición por gnzsoloyo; 20/04/2014 a las 08:02
  #3 (permalink)  
Antiguo 20/04/2014, 10:16
 
Fecha de Ingreso: abril-2014
Mensajes: 72
Antigüedad: 10 años
Puntos: 5
Respuesta: Buscador de música

OK! entendí perfectamente lo que escribiste, ahora mismo me voy a poner a trabajar en cambiar la estructura de la tabla.

Por otro lado, el asunto de los LIKE's es muy importante para mí porque hay muchas canciones e intérpretes con nombres cortos (ejemplo de intérpretes: U2, QBO, JN3, SB4 [o Son by four, donde solo la palabra four sería encontrada] ...), es más, mira estos ejemplos:

1) U2 tiene una canción llamada ONE... ¿Que haríamos si a alguien le interesa buscarla? no podemos sencillamente ignorarlo...

2) Jesse y Joy tienen una canción que se llama mi sol, si el usuario busca mi sol jesse y joy está siendo muy específico pero solamente se buscaría la palabra jesse, trayendo como resultado TODAS las canciones de Jesse y Joy, pero también TODAS las de Jesse Stone, y en un orden impredecible (puede que habiendo sido tan específico, la canción que buscan salga los últimos puestos).

Por el otro lado tienes razón en que si buscamos LIKE %mi% AND LIKE %sol% podría ser peor porque traería ademas todas las canciones que incluyan la palabra SOLEDAD, SOLDADO, COMIDA, etc...

Ahora bien, ¿qué he hecho para solucionar esto? Antes de hacer la consulta MySQL, las palabras escritas por el usuario pasan por un script PHP que es quien da forma a la consulta final, añadiendo al MATCH... AGAINST... los LIKE's de de la siguiente manera:

Búsqueda del usuario: one u2

Consulta MySQL: SELECT todo_lo_necesario FROM las_tablas WHERE MATCH ("one u2") AGAINST (los_campos) OR (campo LIKE '%one %') OR (campo LIKE '% one%') OR (campo LIKE '% one %') OR (campo = 'one') OR (campo LIKE '% u2%') OR (campo LIKE 'u2 %') OR (campo LIKE '% u2 %') OR (campo = 'u2')

De esa manera traería aquellas consultas donde se incluyan las palabras exactas, se encuentren al final, al principio o en el medio de la oración, o bien, sean la única palabra (es decir, traería "one direction" o "one way", pero no traería "se pone bien"). Ahora el problema únicamente sería que no necesariamente las traería en orden.

PARA FINALIZAR: ¿Cual pienso yo que sería la solución correcta? Buscar la manera de que a mayor coincidencia de palabras cortas, la relevancia aumente, así "ONE de U2", estaría primero que las canciones de "ONE DIRECTION" o el resto de las canciones de "U2", por tener dos coincidencias, mientras las otras solo tienen una (también solucionaría lo del orden con el ejemplo de la canción Mi sol de Jesse y Joy). ¿Que piensas? ¿Se podría hacer algo así?

Última edición por zyxer; 20/04/2014 a las 11:12
  #4 (permalink)  
Antiguo 20/04/2014, 15:40
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 4 meses
Puntos: 2658
Respuesta: Buscador de música

Cita:
Iniciado por zyxer Ver Mensaje

Por otro lado, el asunto de los LIKE's es muy importante para mí porque hay muchas canciones e intérpretes con nombres cortos (ejemplo de intérpretes: U2, QBO, JN3, SB4 [o Son by four, donde solo la palabra four sería encontrada] ...), es más, mira estos ejemplos:

1) U2 tiene una canción llamada ONE... ¿Que haríamos si a alguien le interesa buscarla? no podemos sencillamente ignorarlo...

2) Jesse y Joy tienen una canción que se llama mi sol, si el usuario busca mi sol jesse y joy está siendo muy específico pero solamente se buscaría la palabra jesse, trayendo como resultado TODAS las canciones de Jesse y Joy, pero también TODAS las de Jesse Stone, y en un orden impredecible (puede que habiendo sido tan específico, la canción que buscan salga los últimos puestos).

Por el otro lado tienes razón en que si buscamos LIKE %mi% AND LIKE %sol% podría ser peor porque traería ademas todas las canciones que incluyan la palabra SOLEDAD, SOLDADO, COMIDA, etc...

Ahora bien, ¿qué he hecho para solucionar esto? Antes de hacer la consulta MySQL, las palabras escritas por el usuario pasan por un script PHP que es quien da forma a la consulta final, añadiendo al MATCH... AGAINST... los LIKE's de de la siguiente manera:

Búsqueda del usuario: one u2

Consulta MySQL: SELECT todo_lo_necesario FROM las_tablas WHERE MATCH ("one u2") AGAINST (los_campos) OR (campo LIKE '%one %') OR (campo LIKE '% one%') OR (campo LIKE '% one %') OR (campo = 'one') OR (campo LIKE '% u2%') OR (campo LIKE 'u2 %') OR (campo LIKE '% u2 %') OR (campo = 'u2')

De esa manera traería aquellas consultas donde se incluyan las palabras exactas, se encuentren al final, al principio o en el medio de la oración, o bien, sean la única palabra (es decir, traería "one direction" o "one way", pero no traería "se pone bien"). Ahora el problema únicamente sería que no necesariamente las traería en orden.

PARA FINALIZAR: ¿Cual pienso yo que sería la solución correcta? Buscar la manera de que a mayor coincidencia de palabras cortas, la relevancia aumente, así "ONE de U2", estaría primero que las canciones de "ONE DIRECTION" o el resto de las canciones de "U2", por tener dos coincidencias, mientras las otras solo tienen una (también solucionaría lo del orden con el ejemplo de la canción Mi sol de Jesse y Joy). ¿Que piensas? ¿Se podría hacer algo así?
El método más adecuado para búsquedas de casos como el mencionado, surge de analizar cuál es el comportamiento habitual de las personas cuando buscan algo, tal como los ejemplos expuestos dicen.
Habitualmente las personas buscan las palabras que empiezan aproximadamente con un texto determinado, y rara vez buscan uno que termine con tales o cuales palabras.
Por otro lado, cuando se buscan textos intermedios, las personas ingresan palabras completas. Muy, pero muy rara vez, se ingresan partes de palabras.
Estos detalles no los estoy inventando. Si te observas a ti mismo, verás que ese es el modo habitual en que realizas tus propias búsquedas en Google, por ejemplo.

¿Qué implica esto para tu solución?
Bueno, simplemente que es mucho mejor hacer un
Código MySQL:
Ver original
  1. campo LIKE 'palabra%' OR campo LIKE '%palabra'
que hacer
Código MySQL:
Ver original
  1. campo LIKE '%palabra%'
¿Por qué?
Bueno, sencillamente porque al buscar lo que comience o termine con textos concretos, MySQL aplicará los índices que existan, mientras que cuando usas ambos comodines en el mismo LIKE, los descarta. Asi de sencillo.

¿Qué pasa con las palabras intermedias?
En ese caso debes tener en cuenta que cuando alguien busca palabras intermedias, normalmente busca o frases completas, o busca palabras de más de tres letras, y muy rara vez busca tres. Y para esos casos aplica usar indices FULLTEXT, si están disponibles.

Finalmente, como nota: Es posible usar LIKE '%palabra%', pero con ciertas restricciones funcionales:
- Nunca usarlo en campos TEXT, o con campos VARCHAR de más de 150 caracteres (o como máximo 255).
- Nunca usarlo contra tablas que contengan centenares de miles o millones de registros.
- Jamás usarlo cuando el texto a buscar contenga palabras completas, ya que para eso está el caso anterior.
Básicamente, podrías usarlo para la tabla de Autores, o la de Intérpretes, pero no para la de Canciones, si lo pretendes hacer en un campo que contenga la letra de las mismas.
¿Se entiende la idea?
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #5 (permalink)  
Antiguo 20/04/2014, 18:06
 
Fecha de Ingreso: abril-2014
Mensajes: 72
Antigüedad: 10 años
Puntos: 5
Respuesta: Buscador de música

Ok, excelente, entendí la idea y tiene sentido para mi. Muchas gracias, me surge otra pregunta pero creo que debo hacer otro tema para ella. Gracias, toma puntos, que no me cuestan!!! XD

Etiquetas: buscador, campo, php, sql, tabla
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 07:24.