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

Encontrar con "LIKE" sin importar orden de las palabras

Estas en el tema de Encontrar con "LIKE" sin importar orden de las palabras en el foro de Mysql en Foros del Web. Hola amigos, tengo una búsqueda con "LIKE", pero si cambio el orden de las palabras no encuentra los resultados. Estoy usando: SELECT * from TABLE ...
  #1 (permalink)  
Antiguo 20/02/2012, 12:51
 
Fecha de Ingreso: marzo-2009
Mensajes: 61
Antigüedad: 15 años
Puntos: 2
Encontrar con "LIKE" sin importar orden de las palabras

Hola amigos, tengo una búsqueda con "LIKE", pero si cambio el orden de las palabras no encuentra los resultados.

Estoy usando:

SELECT * from TABLE where T1 like '%$term%' or T2 like '%$term%'

digamos que estoy buscando el libro: Critical Thinking Introduction Alec Fisher

si escribo: Alec Fisher
lo encuentra sin ningún problema, pero si pongo: Fisher Alec
ya no encuentra nada

Incluso intenté con MATCH, con esta consulta(ya tengo hechos los índices necesarios para ejecutar MATCH):
SELECT * FROM TABLE WHERE MATCH (T1,T2) AGAINST ('$term')

pero igual, si cambio el orden no encuentra.

En el caso de MATCH no encuentra, porque da preferencia a resultados que contengan Alec o Fisher, antes que al que contiene ambas palabras

Agradezco cualquier sugerencia :)
  #2 (permalink)  
Antiguo 20/02/2012, 15:10
Colaborador
 
Fecha de Ingreso: enero-2007
Ubicación: México
Mensajes: 2.097
Antigüedad: 17 años, 2 meses
Puntos: 447
Respuesta: Encontrar con "LIKE" sin importar orden de las palabras

Hola luisdelbar:

A últimas fechas he venido observando que las preguntas con respecto a búsquedas de texto se han multiplicado, sin embargo no entiendo por qué la insistencia de utilizar LIKE en lugar de MATCH-AGAINST... en más de una ocasión se ha mencionado que hacer LIKE '%algo%' es completamente ineficiente, pues obliga al motor a hacer una búsqueda exhaustiva sobre la tabla... lo que afecta enormemente el rendimiento del servidor.

Creo que el problema es que no se han tomado el tiempo en experimentar las enormes ventajas que proporcionan las búsquedas de texto completo.

Luis, para tu ejemplo, no mencionas que son T1 y T2 pero puedo suponer que se trata de dos campos en tu tabla. quiero imaginar que en uno de ellos almacenas el título del libro y en otro el o los autores. Checa este script:

Código MySQL:
Ver original
  1. mysql> CREATE TABLE tabla (
  2.     -> titulo VARCHAR(200),
  3.     -> autores VARCHAR(200),
  4.     -> FULLTEXT (titulo,autores)
  5.     -> ) ENGINE=MYISAM;
  6. Query OK, 0 rows affected (0.11 sec)
  7.  
  8. mysql> INSERT INTO tabla (titulo, autores) VALUES
  9.     -> ('Critical Thinking Introduction','Alec Fisher'),
  10.     -> ('otro libro','Fisher'),
  11.     -> ('continuación libro','Alec'),
  12.     -> ('otro libro más','otro autor'),
  13.     -> ('Critical Thinking "Introduction"','Alec "el escritor" Fisher'),
  14.     -> ('Alec Fisher', 'Critical Thinking Introduction');
  15. Query OK, 6 rows affected (0.00 sec)
  16. Records: 6  Duplicates: 0  Warnings: 0
  17.  
  18. mysql> SELECT * FROM tabla;
  19. +----+----------------------------------+--------------------------------+
  20. | id | titulo                           | autores                        |
  21. +----+----------------------------------+--------------------------------+
  22. |  1 | Critical Thinking Introduction   | Alec Fisher                    |
  23. |  2 | otro libro                       | Fisher                         |
  24. |  3 | continuación libro               | Alec                           |
  25. |  4 | otro libro más                   | otro autor                     |
  26. |  5 | Critical Thinking "Introduction" | Alec "el escritor" Fisher      |
  27. |  6 | Alec Fisher                      | Critical Thinking Introduction |
  28. +----+----------------------------------+--------------------------------+
  29. 6 rows in set (0.00 sec)
  30.  
  31. mysql> SELECT * FROM tabla
  32.     -> WHERE MATCH (titulo, autores) AGAINST ('Alec Fisher' IN BOOLEAN MODE);
  33. +----+----------------------------------+--------------------------------+
  34. | id | titulo                           | autores                        |
  35. +----+----------------------------------+--------------------------------+
  36. |  1 | Critical Thinking Introduction   | Alec Fisher                    |
  37. |  2 | otro libro                       | Fisher                         |
  38. |  3 | continuación libro               | Alec                           |
  39. |  5 | Critical Thinking "Introduction" | Alec "el escritor" Fisher      |
  40. |  6 | Alec Fisher                      | Critical Thinking Introduction |
  41. +----+----------------------------------+--------------------------------+
  42. 5 rows in set (0.00 sec)
  43.  
  44. mysql> SELECT * FROM tabla
  45.     -> WHERE MATCH (titulo, autores) AGAINST ('Fisher Alec' IN BOOLEAN MODE);
  46. +----+----------------------------------+--------------------------------+
  47. | id | titulo                           | autores                        |
  48. +----+----------------------------------+--------------------------------+
  49. |  1 | Critical Thinking Introduction   | Alec Fisher                    |
  50. |  2 | otro libro                       | Fisher                         |
  51. |  3 | continuación libro               | Alec                           |
  52. |  5 | Critical Thinking "Introduction" | Alec "el escritor" Fisher      |
  53. |  6 | Alec Fisher                      | Critical Thinking Introduction |
  54. +----+----------------------------------+--------------------------------+
  55. 5 rows in set (0.00 sec)

Observa que estoy utilizando el tipo de búsqueda IN BOOLEAN MODE. Independientemente del orden en que ponga el texto a buscar me regresa los registros que contienen al menos una de las palabras a buscar.

Recuerda (o conoce si es que no lo sabes) que aquí no se ordenan registros automáticamente para ordenarlos por relevancia decrecente, aunque podrías poner algo como esto:

Código Python:
Ver original
  1. ORDER BY
  2. MATCH (titulo, autores) AGAINST ('Fisher Alec' IN BOOLEAN MODE) DESC

La expresión "equivalente" para hacer esto mismo con LIKE sería:

Código MySQL:
Ver original
  1. mysql> SELECT * FROM tabla WHERE
  2.     -> titulo LIKE '%Fisher%' OR
  3.     -> autores LIKE '%Fisher%' OR
  4.     -> titulo LIKE '%Alec%' OR
  5.     -> autores LIKE '%Alec%';
  6. +----+----------------------------------+--------------------------------+
  7. | id | titulo                           | autores                        |
  8. +----+----------------------------------+--------------------------------+
  9. |  1 | Critical Thinking Introduction   | Alec Fisher                    |
  10. |  2 | otro libro                       | Fisher                         |
  11. |  3 | continuación libro               | Alec                           |
  12. |  5 | Critical Thinking "Introduction" | Alec "el escritor" Fisher      |
  13. |  6 | Alec Fisher                      | Critical Thinking Introduction |
  14. +----+----------------------------------+--------------------------------+
  15. 5 rows in set (0.00 sec)

Pero aquí no hay modo de saber la relevancia de los resultados obtenidos.

Además, puedes utilizar muchos operadores para las búsquedas booleanas (+, -, <, >, ~, *, (, ), etc.) para hacer aun más exactas tus búsquedas, te recomiendo que le des un vistazo a la documentación oficial para ver todas las ventajas que obtienes al utilizar esto en lugar del LIKE.

http://dev.mysql.com/doc/refman/5.0/...xt-search.html

Saludos
Leo.
  #3 (permalink)  
Antiguo 21/02/2012, 15:25
 
Fecha de Ingreso: marzo-2009
Mensajes: 61
Antigüedad: 15 años
Puntos: 2
Respuesta: Encontrar con "LIKE" sin importar orden de las palabras

Cita:
Iniciado por leonardo_josue Ver Mensaje
Hola luisdelbar:

A últimas fechas he venido observando que las preguntas con respecto a búsquedas de texto se han multiplicado...
Leo Muchísimas gracias por tu explicación tan detallada, estoy haciendo algunas pruebas, ya que soy, novato y autodidacta en esto, y además muuuy lento... jeje. No creo tener problemas.

En efecto T1 y T2 son campos que contienen casi la misma información, con la única diferencia que T2 puede incluir más información adicional, sobre el libro o producto.

Cualquier cosa, te estaré molestando otra vez, pero no creo, muchísimas gracias :)
  #4 (permalink)  
Antiguo 21/02/2012, 16:50
 
Fecha de Ingreso: marzo-2009
Mensajes: 61
Antigüedad: 15 años
Puntos: 2
Respuesta: Encontrar con "LIKE" sin importar orden de las palabras

Cita:
Iniciado por leonardo_josue Ver Mensaje
Hola luisdelbar:

A últimas fechas he venido observando que las preguntas con respecto a búsquedas de texto se han multiplicado
Bueno, estoy aquí de vuelta, parece ser que esto funciona como quería sobre todo con la sugerencia que me diste del ORDER BY que hace lo de dar preferencia primero a los resultados que contengan todas las palabras y ya después pone los que contengan cualquiera de los términos.

Ahora ya sólo un detalle, mi única duda ahora es: ¿como uno lo mismo para 3 tablas?, mi sentencia ya quedó así, y funciona:

501_FIRST_TABLE : es mi tabla
T1,T2 : campos a buscar, contienen casi la misma información, pero T2 tiene info adicional, aunque generalmente contiene lo mismo que T1 pero no siempre
$term : esto es lo que se escribe en la casilla de búsqueda, se trata de un buscador

SELECT * FROM 501_FIRST_TABLE WHERE MATCH (T1,T2) AGAINST ('$term' IN BOOLEAN MODE)
ORDER BY MATCH (T1,T2) AGAINST ('$term' IN BOOLEAN MODE) DESC

y así funciona muy bien, pero quiero unir las tablas:
502_FIRST_TABLE y 503_FIRST_TABLE

Las tablas son idénticas, podría incluso tener los mismos registros en una tabla, la razón por la cual están en 3 es por el peso, pero son iguales.

No puedo hacer lo siguiente, debido a que ya tengo bien adaptado el "paginator" para paginar, y al parecer si hago esto da problema con el paginator, y no quiero adaptar otro método de paginación, para hacerlo funcionar fue un vía crucis, me costó mucho trabajo.

SELECT * FROM 501_FIRST_TABLE,502_FIRST_TABLE,503_FIRST_TABLE WHERE MATCH (T1,T2) AGAINST ('$term' IN BOOLEAN MODE)
ORDER BY MATCH (T1,T2) AGAINST ('$term' IN BOOLEAN MODE) DESC

Aunque funcionara no puedo hacerlo, por el problema con paginator. Pero esta es la forma en que anteriormente estaba uniendo tablas sin que el paginator diera problema:

SELECT * FROM 449_FIRST_TABLE WHERE MATCH (T1,T2) AGAINST ('$term' IN BOOLEAN MODE) UNION
SELECT * FROM 501_FIRST_TABLE WHERE MATCH (T1,T2) AGAINST ('$term' IN BOOLEAN MODE) UNION
SELECT * FROM 502_FIRST_TABLE WHERE MATCH (T1,T2) AGAINST ('$term' IN BOOLEAN MODE)

Todo esto está bien ya con el BOOLEAN MODE como me dijiste, y funciona muy bien, pero para que sea perfecto necesito el ORDER BY ¿Cómo lo pongo?

Muchísimas Gracias!!!
  #5 (permalink)  
Antiguo 22/02/2012, 22:37
 
Fecha de Ingreso: marzo-2009
Mensajes: 61
Antigüedad: 15 años
Puntos: 2
Respuesta: Encontrar con "LIKE" sin importar orden de las palabras

Bueno, logré solucionar todo con este script que armé con un poco de aquí y un poco de allá, no es perfecto, tienes sus detalles, como que no da mucha importancia a palabras con 3 caracteres o menos y cosas así... Pero funciona bastante bien, encuentra sin importar el orden de las palabras y da preferencia primero a los resultados que contienen todas las palabras buscadas (en la mayoría de los casos)

SELECT * , MATCH(T1, T2) AGAINST ('$term') as Score

FROM 449
WHERE MATCH(T1, T2) AGAINST ('$term')



UNION



SELECT * , MATCH(T1, T2) AGAINST ('$term') as Score

FROM 501
WHERE MATCH(T1, T2) AGAINST ('$term')

UNION



SELECT * , MATCH(T1, T2) AGAINST ('$term') as Score

FROM 502
WHERE MATCH(T1, T2) AGAINST ('$term')



ORDER BY Score DESC



En mi caso uní 3 tablas que son idénticas pero que tuve que separar por cuestiones de peso, T1 y T2 son las columnas en las que se buscará, no olvidar que deben tener sus índices FULLTEXT, y bueno 501, 502, 449 las tablas a buscar...

Y bueno, como en mi caso se trata de un buscador, $term equivale a lo que se escribe en la casilla de búsqueda...

Espero que a alguien le sirva y construya cosas buenas... el karma es el karma

luisdelbar • • •
  #6 (permalink)  
Antiguo 23/02/2012, 09:34
Colaborador
 
Fecha de Ingreso: enero-2007
Ubicación: México
Mensajes: 2.097
Antigüedad: 17 años, 2 meses
Puntos: 447
Respuesta: Encontrar con "LIKE" sin importar orden de las palabras

Creo que no haz leído toda la documentación acerca de búsquedas de texto completo, lo que comentas acerca de la longitud de palabras de 3 caracteres o menos es por un parámetro por defecto que tiene el servidor, aunque deberías considerar si realmente quieres hacer esto, de cualquier manera dale un vistazo a esta liga:

http://dev.mysql.com/doc/refman/5.0/...ne-tuning.html

Ahí se muestran algunos puntos que pueden servirte.

Saludos
Leo.
  #7 (permalink)  
Antiguo 27/02/2012, 18:58
 
Fecha de Ingreso: marzo-2009
Mensajes: 61
Antigüedad: 15 años
Puntos: 2
De acuerdo Respuesta: Encontrar con "LIKE" sin importar orden de las palabras

Cita:
Iniciado por leonardo_josue Ver Mensaje
Creo que no haz leído toda la documentación acerca de búsquedas de texto completo, lo que comentas acerca de la longitud de palabras de 3 caracteres o menos es por un parámetro por defecto que tiene el servidor, aunque deberías considerar si realmente quieres hacer esto, de cualquier manera dale un vistazo a esta liga:

http://dev.mysql.com/doc/refman/5.0/...ne-tuning.html

Ahí se muestran algunos puntos que pueden servirte.

Saludos
Leo.
Muchas Gracias, en efecto, aun no la he leído del todo, pero la estoy estudiando poco a poco, y si, ya había leído sobre el umbral del 50% y las palabras de menos de 3 carcteres en la Biblia de MySQL, pero me urgía hacer algo funcional por el momento, y con esas consultas que puse por lo pronto conseguí obtener los resultados que necesitaba, pues la mayoría de las consultas incluyen palabras que tienen más de 3 caracteres.

Sin embargo poco a poco iré refinando eso, pues la verdad estoy aprendiendo todo esto por mi cuenta, sin ningún fundamento formal y la verdad si me está costando trabajo...

Te agradezco mucho la ayuda, ya que fue determinante para que pudiera armar el script final, si no hubiera sido por eso quizá habría dado vueltas y vueltas antes de hallar una solución.

Muchas Gracias!!

Etiquetas: encontrar, orden, palabras, select
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 06:03.