En MySQL, el MATCH()
función realiza una búsqueda de texto completo. Acepta una lista separada por comas de las columnas de la tabla para buscar.
La(s) tabla(s) debe(n) tener un FULLTEXT
index antes de poder realizar una búsqueda de texto completo contra ellos (aunque las consultas booleanas contra un MyISAM
el índice de búsqueda puede funcionar, aunque lentamente, incluso sin un FULLTEXT
índice).
Puede crear un FULLTEXT
índice al crear la tabla (usando el CREATE TABLE
declaración), o puede utilizar la ALTER TABLE
sentencia o CREATE INDEX
instrucción si la tabla ya existe.
De forma predeterminada, la búsqueda no distingue entre mayúsculas y minúsculas. Para realizar una búsqueda que distinga entre mayúsculas y minúsculas, utilice una intercalación binaria o que distinga entre mayúsculas y minúsculas para las columnas indexadas.
Sintaxis
La sintaxis para MATCH()
la función es así:
MATCH (col1,col2,...) AGAINST (expr [search_modifier])
Donde col1,col2,...
es la lista de columnas separadas por comas para buscar, y expr
es la cadena/expresión de entrada.
El search_modifier
opcional El argumento le permite especificar el tipo de búsqueda. Puede ser cualquiera de los siguientes valores:
IN NATURAL LANGUAGE MODE
IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION
IN BOOLEAN MODE
WITH QUERY EXPANSION
El modo predeterminado es IN NATURAL LANGUAGE MODE
.
Ejemplo 1:uso básico
Aquí hay un ejemplo de cómo usar esta función:
SELECT AlbumId, AlbumName FROM Albums WHERE MATCH(AlbumName) AGAINST('cool');
Resultado:
+---------+--------------------+ | AlbumId | AlbumName | +---------+--------------------+ | 5 | Casualties of Cool | +---------+--------------------+
Aquí está la tabla completa en la que se ejecutó la consulta anterior:
SELECT AlbumId, AlbumName FROM Albums;
Resultado:
+---------+--------------------------+ | AlbumId | AlbumName | +---------+--------------------------+ | 1 | Powerslave | | 2 | Powerage | | 3 | Singing Down the Lane | | 4 | Ziltoid the Omniscient | | 5 | Casualties of Cool | | 6 | Epicloud | | 7 | Somewhere in Time | | 8 | Piece of Mind | | 9 | Killers | | 10 | No Prayer for the Dying | | 11 | No Sound Without Silence | | 12 | Big Swing Face | | 13 | Blue Night | | 14 | Eternity | | 15 | Scandinavia | | 16 | Long Lost Suitcase | | 17 | Praise and Blame | | 18 | Along Came Jones | | 19 | All Night Wrong | | 20 | The Sixteen Men of Tain | +---------+--------------------------+
Ejemplo 2:error:"No se puede encontrar el índice FULLTEXT"
InnoDB
las tablas deben tener un FULLTEXT
index antes de que devuelva los resultados de una búsqueda de texto completo. Si no tiene un FULLTEXT
index, es probable que obtenga el siguiente error:
ERROR 1191 (HY000): Can't find FULLTEXT index matching the column list
Si recibe ese error, deberá agregar un FULLTEXT
índice para todas las columnas que está tratando de buscar (vea el siguiente ejemplo).
La excepción a esto podría ser si está ejecutando una consulta booleana contra un MyISAM
índice de búsqueda.
Para ser más específicos, la documentación de MySQL para búsquedas booleanas de texto completo establece lo siguiente:
InnoDB
las tablas requieren un FULLTEXT
índice en todas las columnas del MATCH()
expresión para realizar consultas booleanas. Consultas booleanas contra un MyISAM
el índice de búsqueda puede funcionar incluso sin un FULLTEXT
index, aunque una búsqueda ejecutada de esta manera sería bastante lenta.
Ejemplo 3:agregar un índice FULLTEXT a una tabla existente
Aquí hay un ejemplo de cómo agregar un FULLTEXT
índice a una tabla existente:
ALTER TABLE Albums ADD FULLTEXT(AlbumName);
En este caso, indexé el contenido de AlbumName
columna.
Para indexar varias columnas, sepárelas con una coma (vea el siguiente ejemplo).
Ejemplo 4:búsqueda en varias columnas
Si cree que necesitará buscar en más de una columna, deberá crear un índice que incluya todas las columnas que se van a buscar. Para hacer esto, simplemente incluya cada columna como una lista separada por comas.
Aquí hay un ejemplo donde agrego un FULLTEXT
índice de la film
table (que forma parte de la base de datos de ejemplo de Sakila).
ALTER TABLE film ADD FULLTEXT(title, description);
En este caso, indexo el contenido del title
y description
columnas.
Ahora que hemos creado un FULLTEXT
index para ambas columnas, podemos hacer una búsqueda de texto completo contra ellas:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('vertigo');
Resultado:
+-------------------+-----------------------------------------------------------------------------------------------------------+ | title | description | +-------------------+-----------------------------------------------------------------------------------------------------------+ | VERTIGO NORTHWEST | A Unbelieveable Display of a Mad Scientist And a Mad Scientist who must Outgun a Mad Cow in Ancient Japan | +-------------------+-----------------------------------------------------------------------------------------------------------+
Aquí hay otra búsqueda, donde la frase clave exacta no coincide, pero cada palabra clave dentro de esa frase sí:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('Iron Maiden');
Resultado:
+-------------+---------------------------------------------------------------------------------------------------------+ | title | description | +-------------+---------------------------------------------------------------------------------------------------------+ | IRON MOON | A Fast-Paced Documentary of a Mad Cow And a Boy who must Pursue a Dentist in A Baloon | | MAIDEN HOME | A Lacklusture Saga of a Moose And a Teacher who must Kill a Forensic Psychologist in A MySQL Convention | +-------------+---------------------------------------------------------------------------------------------------------+
Si solo desea que coincida la frase exacta, coloque comillas dobles alrededor:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('"Iron Maiden"');
Resultado:
Empty set (0.00 sec)
En este caso, ninguna de las columnas contiene esa frase exacta.
Ejemplo 5:devuelve la puntuación de relevancia
Siempre que utilice el MATCH()
función, a cada fila de la tabla se le asigna un valor de relevancia. En otras palabras, cada fila obtiene una puntuación que determina qué tan relevante es para el término de búsqueda. Luego, los resultados se ordenan por relevancia (primero la de mayor relevancia).
Los valores de relevancia son números de coma flotante no negativos. Relevancia cero significa que no hay similitud. La relevancia se calcula según la cantidad de palabras en la fila (documento), la cantidad de palabras únicas en la fila, la cantidad total de palabras en la colección y la cantidad de filas que contienen una palabra en particular.
Para devolver la relevancia de cada resultado, simplemente incluya el MATCH()
función en su lista de columnas para seleccionar.
Ejemplo:
SELECT MATCH(title, description) AGAINST('Iron Maiden') AS Relevance, title, description FROM film WHERE MATCH(title, description) AGAINST('Iron Maiden');
Resultado:
+-----------+-------------+---------------------------------------------------------------------------------------------------------+ | Relevance | title | description | +-----------+-------------+---------------------------------------------------------------------------------------------------------+ | 9 | IRON MOON | A Fast-Paced Documentary of a Mad Cow And a Boy who must Pursue a Dentist in A Baloon | | 9 | MAIDEN HOME | A Lacklusture Saga of a Moose And a Teacher who must Kill a Forensic Psychologist in A MySQL Convention | +-----------+-------------+---------------------------------------------------------------------------------------------------------+
En este caso, la puntuación de relevancia es muy alta para ambas filas.
Aquí hay otro donde la relevancia es menor:
SELECT MATCH(title, description) AGAINST('Saga of a Moose') AS Relevance, title, description FROM film WHERE MATCH(title, description) AGAINST('Saga of a Moose') LIMIT 15;
Resultado:
+--------------------+------------------------+---------------------------------------------------------------------------------------------------------+ | Relevance | title | description | +--------------------+------------------------+---------------------------------------------------------------------------------------------------------+ | 2.4431142807006836 | CAPER MOTIONS | A Fateful Saga of a Moose And a Car who must Pursue a Woman in A MySQL Convention | | 2.4431142807006836 | DATE SPEED | A Touching Saga of a Composer And a Moose who must Discover a Dentist in A MySQL Convention | | 2.4431142807006836 | DELIVERANCE MULHOLLAND | A Astounding Saga of a Monkey And a Moose who must Conquer a Butler in A Shark Tank | | 2.4431142807006836 | FLASH WARS | A Astounding Saga of a Moose And a Pastry Chef who must Chase a Student in The Gulf of Mexico | | 2.4431142807006836 | HAROLD FRENCH | A Stunning Saga of a Sumo Wrestler And a Student who must Outrace a Moose in The Sahara Desert | | 2.4431142807006836 | MAIDEN HOME | A Lacklusture Saga of a Moose And a Teacher who must Kill a Forensic Psychologist in A MySQL Convention | | 2.4431142807006836 | SHANE DARKNESS | A Action-Packed Saga of a Moose And a Lumberjack who must Find a Woman in Berlin | | 2.4431142807006836 | SLEEPLESS MONSOON | A Amazing Saga of a Moose And a Pastry Chef who must Escape a Butler in Australia | | 2.4431142807006836 | WAKE JAWS | A Beautiful Saga of a Feminist And a Composer who must Challenge a Moose in Berlin | | 2.4431142807006836 | WONKA SEA | A Brilliant Saga of a Boat And a Mad Scientist who must Meet a Moose in Ancient India | | 1.2399028539657593 | AIRPLANE SIERRA | A Touching Saga of a Hunter And a Butler who must Discover a Butler in A Jet Boat | | 1.2399028539657593 | ALASKA PHANTOM | A Fanciful Saga of a Hunter And a Pastry Chef who must Vanquish a Boy in Australia | | 1.2399028539657593 | ARMY FLINTSTONES | A Boring Saga of a Database Administrator And a Womanizer who must Battle a Waitress in Nigeria | | 1.2399028539657593 | BEAR GRACELAND | A Astounding Saga of a Dog And a Boy who must Kill a Teacher in The First Manned Space Station | | 1.2399028539657593 | BERETS AGENT | A Taut Saga of a Crocodile And a Boy who must Overcome a Technical Writer in Ancient China | +--------------------+------------------------+---------------------------------------------------------------------------------------------------------+
Tenga en cuenta que el conjunto de resultados habría sido mucho mayor si no hubiera usado LIMIT 15
para limitar el número de resultados a 15.
Ejemplo 6:solo devuelve resultados por encima de una determinada puntuación de relevancia
Podemos llevar el ejemplo anterior un paso más allá y filtrar solo aquellos resultados con una determinada puntuación de relevancia. En este caso especifico que la puntuación de relevancia debe ser superior a 2.
Sin embargo, tenga cuidado al hacer esto. Como se vio anteriormente, los valores de relevancia pueden ser muy altos o muy bajos, dependiendo de factores como cuánto texto hay en la columna, cuántas otras filas coinciden con el término de búsqueda, etc.
SELECT MATCH(title, description) AGAINST('Saga of a Moose') AS Relevance, title, description FROM film WHERE MATCH(title, description) AGAINST('Saga of a Moose') > 2;
Resultado:
+--------------------+------------------------+---------------------------------------------------------------------------------------------------------+ | Relevance | title | description | +--------------------+------------------------+---------------------------------------------------------------------------------------------------------+ | 2.4431142807006836 | CAPER MOTIONS | A Fateful Saga of a Moose And a Car who must Pursue a Woman in A MySQL Convention | | 2.4431142807006836 | DATE SPEED | A Touching Saga of a Composer And a Moose who must Discover a Dentist in A MySQL Convention | | 2.4431142807006836 | DELIVERANCE MULHOLLAND | A Astounding Saga of a Monkey And a Moose who must Conquer a Butler in A Shark Tank | | 2.4431142807006836 | FLASH WARS | A Astounding Saga of a Moose And a Pastry Chef who must Chase a Student in The Gulf of Mexico | | 2.4431142807006836 | HAROLD FRENCH | A Stunning Saga of a Sumo Wrestler And a Student who must Outrace a Moose in The Sahara Desert | | 2.4431142807006836 | MAIDEN HOME | A Lacklusture Saga of a Moose And a Teacher who must Kill a Forensic Psychologist in A MySQL Convention | | 2.4431142807006836 | SHANE DARKNESS | A Action-Packed Saga of a Moose And a Lumberjack who must Find a Woman in Berlin | | 2.4431142807006836 | SLEEPLESS MONSOON | A Amazing Saga of a Moose And a Pastry Chef who must Escape a Butler in Australia | | 2.4431142807006836 | WAKE JAWS | A Beautiful Saga of a Feminist And a Composer who must Challenge a Moose in Berlin | | 2.4431142807006836 | WONKA SEA | A Brilliant Saga of a Boat And a Mad Scientist who must Meet a Moose in Ancient India | +--------------------+------------------------+---------------------------------------------------------------------------------------------------------+
Ejemplo 7:incluir resultados de relevancia cero
Aquí hay un ejemplo de una lista de los valores de relevancia para cada fila, incluso si el valor de relevancia es cero. Podemos hacer esto al no usar MATCH()
función en el WHERE
cláusula.
En este ejemplo, en realidad no uso un WHERE
cláusula. Solo uso un LIMIT
cláusula para limitar el número de resultados.
SELECT MATCH(title, description) AGAINST('Scientist') AS Relevance, title, description FROM film LIMIT 15;
Resultado:
+-------------------+------------------+-----------------------------------------------------------------------------------------------------------------------+ | Relevance | title | description | +-------------------+------------------+-----------------------------------------------------------------------------------------------------------------------+ | 1.026631474494934 | ACADEMY DINOSAUR | A Epic Drama of a Feminist And a Mad Scientist who must Battle a Teacher in The Canadian Rockies | | 0 | ACE GOLDFINGER | A Astounding Epistle of a Database Administrator And a Explorer who must Find a Car in Ancient China | | 0 | ADAPTATION HOLES | A Astounding Reflection of a Lumberjack And a Car who must Sink a Lumberjack in A Baloon Factory | | 0 | AFFAIR PREJUDICE | A Fanciful Documentary of a Frisbee And a Lumberjack who must Chase a Monkey in A Shark Tank | | 0 | AFRICAN EGG | A Fast-Paced Documentary of a Pastry Chef And a Dentist who must Pursue a Forensic Psychologist in The Gulf of Mexico | | 0 | AGENT TRUMAN | A Intrepid Panorama of a Robot And a Boy who must Escape a Sumo Wrestler in Ancient China | | 0 | AIRPLANE SIERRA | A Touching Saga of a Hunter And a Butler who must Discover a Butler in A Jet Boat | | 0 | AIRPORT POLLOCK | A Epic Tale of a Moose And a Girl who must Confront a Monkey in Ancient India | | 2.053262948989868 | ALABAMA DEVIL | A Thoughtful Panorama of a Database Administrator And a Mad Scientist who must Outgun a Mad Scientist in A Jet Boat | | 0 | ALADDIN CALENDAR | A Action-Packed Tale of a Man And a Lumberjack who must Reach a Feminist in Ancient China | | 0 | ALAMO VIDEOTAPE | A Boring Epistle of a Butler And a Cat who must Fight a Pastry Chef in A MySQL Convention | | 0 | ALASKA PHANTOM | A Fanciful Saga of a Hunter And a Pastry Chef who must Vanquish a Boy in Australia | | 0 | ALI FOREVER | A Action-Packed Drama of a Dentist And a Crocodile who must Battle a Feminist in The Canadian Rockies | | 0 | ALICE FANTASIA | A Emotional Drama of a A Shark And a Database Administrator who must Vanquish a Pioneer in Soviet Georgia | | 1.026631474494934 | ALIEN CENTER | A Brilliant Drama of a Cat And a Mad Scientist who must Battle a Feminist in A MySQL Convention | +-------------------+------------------+-----------------------------------------------------------------------------------------------------------------------+
Ejemplo 8:modo booleano
MySQL nos permite ejecutar búsquedas de texto completo en modo booleano. Para hacer esto, agregue el IN BOOLEAN MODE
modificador a su consulta.
El modo booleano le permite usar operadores como +
y -
para especificar si una palabra o frase en particular debe o no estar presente.
En el siguiente ejemplo, prefijo cada palabra con un signo más (+
) para indicar que ambas palabras deben estar presentes.
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('+Saga +Moose' IN BOOLEAN MODE) LIMIT 3;
Resultado:
+------------------------+---------------------------------------------------------------------------------------------+ | title | description | +------------------------+---------------------------------------------------------------------------------------------+ | CAPER MOTIONS | A Fateful Saga of a Moose And a Car who must Pursue a Woman in A MySQL Convention | | DATE SPEED | A Touching Saga of a Composer And a Moose who must Discover a Dentist in A MySQL Convention | | DELIVERANCE MULHOLLAND | A Astounding Saga of a Monkey And a Moose who must Conquer a Butler in A Shark Tank | +------------------------+---------------------------------------------------------------------------------------------+
En el siguiente ejemplo, cambio uno de los signos más por un signo menos (-
). Esto significa que solo aquellas filas que contengan la palabra Saga
serán devueltos, pero solo si no también contienen Moose
:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('+Saga -Moose' IN BOOLEAN MODE) LIMIT 3;
Resultado:
+------------------+-------------------------------------------------------------------------------------------------+ | title | description | +------------------+-------------------------------------------------------------------------------------------------+ | AIRPLANE SIERRA | A Touching Saga of a Hunter And a Butler who must Discover a Butler in A Jet Boat | | ALASKA PHANTOM | A Fanciful Saga of a Hunter And a Pastry Chef who must Vanquish a Boy in Australia | | ARMY FLINTSTONES | A Boring Saga of a Database Administrator And a Womanizer who must Battle a Waitress in Nigeria | +------------------+-------------------------------------------------------------------------------------------------+
El signo menos se utiliza para excluir resultados que, de otro modo, se devolverían. Por lo tanto, si todas nuestras palabras de búsqueda tienen el prefijo de un signo menos, se devuelve un conjunto vacío.
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('-Saga -Moose' IN BOOLEAN MODE) LIMIT 3;
Resultado:
Empty set (0.00 sec)
Hay muchos más operadores que se pueden usar con búsquedas booleanas, como ~
, <
, >
, *
, y más. Para obtener información más detallada sobre el uso del modo booleano, consulte la documentación de MySQL para búsquedas booleanas de texto completo.
Ejemplo 9:con expansión de consulta ciega
Puede usar WITH QUERY EXPANSION
o el IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION
modificadores para realizar la expansión de consulta ciega. Esto puede ser útil cuando la frase de búsqueda es muy corta y los resultados devueltos podrían ser demasiado limitados (excluyendo así documentos potencialmente relevantes).
La expansión de consultas puede ampliar la búsqueda al devolver filas que de otro modo no se devolverían. En particular, si una fila no coincidente contiene palabras que también están contenidas en una fila coincidente, esa fila no coincidente podría convertirse en una fila coincidente. En otras palabras, aún se puede devolver una fila que no coincide, simplemente porque comparte otras palabras con una fila coincidente.
Para demostrarlo, aquí hay una búsqueda normal sin consulta de expansión:
SELECT AlbumId, AlbumName FROM Albums WHERE MATCH(AlbumName) AGAINST('Blue' IN NATURAL LANGUAGE MODE);
Resultado:
+---------+------------+ | AlbumId | AlbumName | +---------+------------+ | 13 | Blue Night | +---------+------------+
Indiqué explícitamente IN NATURAL LANGUAGE MODE
pero este es el modo predeterminado, por lo que también podría haber omitido este modificador si así lo hubiera elegido.
Y aquí está la misma búsqueda con consulta de expansión:
SELECT AlbumId, AlbumName FROM Albums WHERE MATCH(AlbumName) AGAINST('Blue' WITH QUERY EXPANSION);
Resultado:
+---------+-----------------+ | AlbumId | AlbumName | +---------+-----------------+ | 13 | Blue Night | | 19 | All Night Wrong | +---------+-----------------+
En este caso, se devuelven dos resultados. Observe cómo el segundo resultado no contiene la frase de búsqueda (blue
). Pero contiene la palabra Night
que también está en el primer resultado. Entonces, la consulta ampliada lo considera lo suficientemente bueno como para ser una coincidencia.
Los nombres de los álbumes probablemente no sean un buen caso de uso para el modo de expansión de consultas. Un mejor caso de uso podría ser una búsqueda de, por ejemplo, base de datos , donde una consulta expandida también puede devolver documentos que contienen nombres como MySQL , Oráculo , etc. incluso si no contienen la frase base de datos .
Aquí hay otro ejemplo. Sin embargo, este ejemplo usa comillas dobles para especificar que el término de búsqueda completo debe estar presente.
Si hacemos la búsqueda sin consulta de expansión:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('"Feminist And a Mad Scientist"') LIMIT 3;
Resultado:
+------------------+--------------------------------------------------------------------------------------------------+ | title | description | +------------------+--------------------------------------------------------------------------------------------------+ | ACADEMY DINOSAUR | A Epic Drama of a Feminist And a Mad Scientist who must Battle a Teacher in The Canadian Rockies | +------------------+--------------------------------------------------------------------------------------------------+
Solo se devuelve un resultado (es el único resultado que contiene la frase completa, exactamente como se escribió).
Pero si usamos la expansión de consultas ciegas, esto es lo que sucede:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('"Feminist And a Mad Scientist"' WITH QUERY EXPANSION) LIMIT 3;
Resultado:
+--------------------+------------------------------------------------------------------------------------------------------+ | title | description | +--------------------+------------------------------------------------------------------------------------------------------+ | ACADEMY DINOSAUR | A Epic Drama of a Feminist And a Mad Scientist who must Battle a Teacher in The Canadian Rockies | | DINOSAUR SECRETARY | A Action-Packed Drama of a Feminist And a Girl who must Reach a Robot in The Canadian Rockies | | VICTORY ACADEMY | A Insightful Epistle of a Mad Scientist And a Explorer who must Challenge a Cat in The Sahara Desert | +--------------------+------------------------------------------------------------------------------------------------------+
La primera fila es la misma que cuando no usamos la expansión de consultas. Sin embargo, la consulta va y devuelve filas que solo contienen partes de nuestro término de búsqueda. Este resultado está limitado a tres solo porque usé LIMIT 3
. Los resultados reales son mucho mayores:
SELECT COUNT(*) FROM film WHERE MATCH(title, description) AGAINST('"Feminist And a Mad Scientist"' WITH QUERY EXPANSION);
Resultado:
+----------+ | COUNT(*) | +----------+ | 1000 | +----------+
Es muy posible que muchos de esos resultados sean completamente irrelevantes para el término de búsqueda. Por lo tanto, la expansión de consulta ciega generalmente funciona mejor para términos de búsqueda más cortos.
Para obtener más información sobre el uso de la expansión de consultas ciegas, consulte la documentación de MySQL:Búsquedas de texto completo con expansión de consultas.