2011-08-19 18 views
6

Soy bastante nuevo en las búsquedas de texto completo de MySQL y me encontré con este problema hoy en día:MySQL modo booleano búsqueda de texto completo con comodines y literales

Mi mesa compañía tiene un registro con "e-revista AG" en el nombre de la columna Tengo un índice de texto completo en la columna de nombre.

Cuando ejecuta esta consulta no se encuentra el registro:

SELECT id, name FROM company WHERE MATCH(name) AGAINST('+"e-magazi"*' IN BOOLEAN MODE); 

que necesito trabajar con citas debido al guión y al utilizar el comodín porque implemento una "búsqueda mientras se escribe" funcionalidad.

Cuando busco el término completo "e-magazine AG", se encuentra el registro.

¿Alguna idea de lo que estoy haciendo mal aquí? Leí acerca de agregar el guión a la lista de caracteres de las palabras (se necesita una actualización de configuración), pero estoy buscando una forma de hacerlo mediante programación.

+0

pregunta interesante. Puedo replicarlo aquí en una tabla con un campo similar a uuid. 'SELECT id, bootid FROM socket WHERE MATCH (bootid) CONTRA ('+" 18bda775 "' EN MODO BOOLEANO);' funcionará y también lo hará si busco "18bda775-711c", pero busco "18bda" o "18bda775" -711 "no funcionará. el campo 'bootid' en cuestión contiene: 18bda775-711c-4329-9de2-a3d81dc13d06 –

+0

También tratamos de cambiar los caracteres de control booleanos para usar # en lugar de - pero no tuvo efecto (sí, repare el índice de la tabla después del cambio) : 'ft_boolean_syntax = + #><() ~ *:" "& |' – hajo

Respuesta

2

Esta cláusula

MATCH(name) AGAINST('+"e-magazi"*' IN BOOLEAN MODE); 

buscará un AND "e" AND NOT "magazi"; es decir, - dentro de "e-magazi" se interpretará como not aunque esté entre comillas.
Por esta razón, no funcionará como se esperaba.
Una solución es aplicar una cláusula adicional having con un LIKE.

Sé que having es lento, pero solo se aplicará a los resultados de la coincidencia, por lo que no se deben involucrar demasiadas filas.

me sugieren algo como:

SELECT id, name 
FROM company 
WHERE MATCH(name) AGAINST('magazine' IN BOOLEAN MODE) 
HAVING name LIKE '%e-magazi%'; 
+0

gracias por la información pero no me sirve porque la cadena de búsqueda es ingresada por el usuario que quiere buscar una empresa.en otras palabras, el servidor que ejecuta la consulta no puede saber que "e-magazi" es parte de la cadena "e-magazine". el campo de búsqueda debe aceptar tanto partes de palabras como palabras completas. – hajo

+0

¡Método muy exclusivo para el método de filtrado! ¡Gracias! – ProfileTwist

+0

¿Dónde ves espacios en blanco al frente o después de la frase de búsqueda? ¡El '+' es un operador de texto completo regular y no un espacio en blanco! – mgutt

0

MySQL trata texto completo de la palabra en un texto e-magazine como frase y no como una palabra. Por eso resulta el dos palabras e y magazine. Y mientras construye el índice de búsqueda, no agrega el e al índice debido al ft_min_word_len (el valor predeterminado es 4 caracteres).

La misma limitación de longitud se utiliza para la consulta de búsqueda. Ese es el motivo por el que una búsqueda de e-magazine devuelve exactamente los mismos resultados que a-magazine porque a y - se ignoran por completo.

Pero ahora usted quiere encontrar la frase exacta e-magazine.Por que utilice las comillas y que es la forma correcta completa para encontrar frases, pero MySQL no soporta los operadores de frases, sólo para decir:
https://dev.mysql.com/doc/refman/5.7/en/fulltext-boolean.html

Con este modificador, ciertos caracteres tienen un significado especial en el principio o al final de las palabras en la cadena de búsqueda

Algunas personas sugieren utilizar la siguiente consulta:

SELECT id, name 
FROM company 
WHERE MATCH(name) AGAINST('e-magazi*' IN BOOLEAN MODE) 
HAVING name LIKE 'e-magazi%'; 

Como dije, MySQL ignora el e- y busca la palabra comodín magazi*. Después de que se obtengan esos resultados, utiliza HAVING para filtrar los resultados de e-magazi*, incluido el e-. Con eso encontrarás la frase e-magazine AG. Por supuesto, solo se necesita HAVING si la frase de búsqueda contiene el operador comodín y nunca debe usar comillas. ¡Este operador es utilizado por su usuario y no usted!

Nota: Siempre que no rodee la frase de búsqueda con % encontrará solo los campos que comienzan con esa palabra. Y no quiere rodearlo, porque también encontrará bee-magazine. Entonces tal vez necesites un OR HAVING name LIKE ' %e-magazi%' OR HAVING NAME LIKE '\\n%e-magazi%' adicional para hacerlo utilizable dentro de los textos.

truco

Pero, finalmente, yo prefiero un truco tan HAVING no es necesaria en absoluto:

  1. Si agrega textos a su tabla de base de datos, añadir, además, a una columna de texto completo separado indexados y reemplace palabras como up-to-date con up-to-date uptodate.
  2. Si un usuario busca up-to-date, reemplácelo en la consulta con uptodate.

Por que aún se pueden encontrar en specificuser-specific pero up-to-date así (y no sólo date).

Bono

Si un usuario busca -well-known huge ports MySQL trata como not include *well*, could include *known* and *huge*. Por supuesto que podría resolver ese otro con una variante de consulta adicional, así, pero con el truco anterior se retire el guión por lo que la consulta de búsqueda se ve simplemente como eso:

SELECT id 
FROM texts 
WHERE MATCH(text) AGAINST('-wellknown huge ports' IN BOOLEAN MODE) 
Cuestiones relacionadas