Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Como a função MATCH() funciona no MySQL


No MySQL, o MATCH() função executa uma pesquisa de texto completo. Ele aceita uma lista separada por vírgulas de colunas de tabela a serem pesquisadas.

A(s) tabela(s) deve(m) ter um FULLTEXT index antes que você possa fazer uma pesquisa de texto completo neles (embora as consultas booleanas em um MyISAM o índice de pesquisa pode funcionar - embora lentamente - mesmo sem um FULLTEXT índice).

Você pode criar um FULLTEXT index ao criar a tabela (usando o CREATE TABLE instrução), ou você pode usar o ALTER TABLE instrução ou o CREATE INDEX declaração se a tabela já existir.

Por padrão, a pesquisa não diferencia maiúsculas de minúsculas. Para realizar uma pesquisa com distinção entre maiúsculas e minúsculas, use uma ordenação binária ou com distinção entre maiúsculas e minúsculas para as colunas indexadas.


Sintaxe


A sintaxe para o MATCH() função fica assim:
MATCH (col1,col2,...) AGAINST (expr [search_modifier])

Onde col1,col2,... é a lista de colunas separadas por vírgulas para pesquisar e expr é a string/expressão de entrada.

O search_modifier opcional O argumento permite especificar o tipo de pesquisa. Pode ser qualquer um dos seguintes valores:
  • IN NATURAL LANGUAGE MODE
  • IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION
  • IN BOOLEAN MODE
  • WITH QUERY EXPANSION

O modo padrão é IN NATURAL LANGUAGE MODE .

Exemplo 1 – Uso básico


Veja um exemplo de como usar esta função:
SELECT AlbumId, AlbumName
FROM Albums
WHERE MATCH(AlbumName) AGAINST('cool');

Resultado:
+---------+--------------------+
| AlbumId | AlbumName          |
+---------+--------------------+
|       5 | Casualties of Cool |
+---------+--------------------+

Aqui está a tabela completa em que a consulta acima foi executada:
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  |
+---------+--------------------------+

Exemplo 2 – Erro:“Não é possível encontrar o índice FULLTEXT”


InnoDB as tabelas devem ter um FULLTEXT index antes de retornar resultados de uma pesquisa de texto completo. Se não tiver um FULLTEXT index, você provavelmente receberá o seguinte erro:
ERROR 1191 (HY000): Can't find FULLTEXT index matching the column list

Se você receber esse erro, precisará adicionar um FULLTEXT index para todas as colunas que você está tentando pesquisar (veja o próximo exemplo).

A exceção a isso pode ser se você estiver executando uma consulta booleana em um MyISAM índice de pesquisa.

Para ser mais específico, a documentação do MySQL para pesquisas de texto completo booleanas afirma o seguinte:

InnoDB as tabelas requerem um FULLTEXT índice em todas as colunas do MATCH() expressão para realizar consultas booleanas. Consultas booleanas em um MyISAM o índice de pesquisa pode funcionar mesmo sem um FULLTEXT index, embora uma busca executada desta forma seja bastante lenta.

Exemplo 3 – Adicionando um índice FULLTEXT a uma tabela existente


Aqui está um exemplo de como adicionar um FULLTEXT index para uma tabela existente:
ALTER TABLE Albums  
ADD FULLTEXT(AlbumName);

Nesse caso, indexei o conteúdo do AlbumName coluna.

Para indexar várias colunas, separe-as com uma vírgula (veja o próximo exemplo).

Exemplo 4 – Pesquisando várias colunas


Se você acha que precisará pesquisar mais de uma coluna, precisará criar um índice que inclua todas as colunas a serem pesquisadas. Para fazer isso, basta incluir cada coluna como uma lista separada por vírgulas.

Aqui está um exemplo onde eu adiciono um FULLTEXT índice para o film table (que faz parte do banco de dados de exemplo Sakila).
ALTER TABLE film 
ADD FULLTEXT(title, description);

Neste caso, eu indexo o conteúdo do title e description colunas.

Agora que criamos um FULLTEXT index para ambas as colunas, podemos fazer uma pesquisa de texto completo nelas:
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 |
+-------------------+-----------------------------------------------------------------------------------------------------------+

Aqui está outra pesquisa, onde a frase-chave exata não corresponde, mas cada palavra-chave dentro dessa frase corresponde:
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 |
+-------------+---------------------------------------------------------------------------------------------------------+

Se você quiser apenas que a frase exata corresponda, coloque aspas duplas em torno dela:
SELECT title, description
FROM film
WHERE MATCH(title, description) AGAINST('"Iron Maiden"');

Resultado:
Empty set (0.00 sec)

Nesse caso, nenhuma das colunas contém essa frase exata.

Exemplo 5 – Retornar a pontuação de relevância


Sempre que você usar o MATCH() função, cada linha na tabela recebe um valor de relevância. Em outras palavras, cada linha recebe uma pontuação que determina o quão relevante é para o termo de pesquisa. Os resultados são então ordenados por relevância (maior relevância primeiro).

Os valores de relevância são números de ponto flutuante não negativos. Relevância zero significa ausência de similaridade. A relevância é calculada com base no número de palavras na linha (documento), no número de palavras exclusivas na linha, no número total de palavras na coleção e no número de linhas que contêm uma palavra específica.

Para retornar a relevância de cada resultado, basta incluir o MATCH() função em sua lista de colunas para selecionar.

Exemplo:
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 |
+-----------+-------------+---------------------------------------------------------------------------------------------------------+

Nesse caso, a pontuação de relevância é muito alta para ambas as linhas.

Aqui está outro onde a relevância é 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              |
+--------------------+------------------------+---------------------------------------------------------------------------------------------------------+

Observe que o conjunto de resultados teria sido muito maior se eu não tivesse usado LIMIT 15 limitar o número de resultados a 15.

Exemplo 6 - Retornar apenas resultados acima de uma certa pontuação de relevância


Podemos levar o exemplo anterior um passo adiante e filtrar apenas os resultados com uma determinada pontuação de relevância. Nesse caso, especifico que a pontuação de relevância deve ser maior que 2.

Tenha cuidado ao fazer isso embora. Como visto acima, os valores de relevância podem ser muito altos ou muito baixos, dependendo de fatores como a quantidade de texto na coluna, quantas outras linhas correspondem ao termo de pesquisa 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                   |
+--------------------+------------------------+---------------------------------------------------------------------------------------------------------+

Exemplo 7 - Incluir resultados de relevância zero


Aqui está um exemplo de listagem dos valores de relevância para cada linha, mesmo que o valor de relevância seja zero. Podemos fazer isso não usando o MATCH() função no WHERE cláusula.

Neste exemplo, eu realmente não uso um WHERE cláusula. Eu uso apenas um LIMIT cláusula para limitar o 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                       |
+-------------------+------------------+-----------------------------------------------------------------------------------------------------------------------+

Exemplo 8 – Modo booleano


O MySQL nos permite executar pesquisas de texto completo no modo booleano. Para fazer isso, adicione o IN BOOLEAN MODE modificador para sua consulta.

O modo booleano permite que você use operadores como + e - para especificar se uma determinada palavra ou frase deve ou não estar presente.

No exemplo a seguir, prefixo cada palavra com um sinal de mais (+ ) para indicar que ambas as palavras devem 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         |
+------------------------+---------------------------------------------------------------------------------------------+

No próximo exemplo, altero um dos sinais de mais para um sinal de menos (- ). Isso significa que apenas as linhas que contêm a palavra Saga serão devolvidos, mas somente se não também contém 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 |
+------------------+-------------------------------------------------------------------------------------------------+

O sinal de menos é usado para excluir resultados que de outra forma seriam retornados. Portanto, se todas as nossas palavras de pesquisa forem prefixadas com um sinal de menos, um conjunto vazio será retornado.
SELECT 
  title, 
  description
FROM film
WHERE MATCH(title, description) AGAINST('-Saga -Moose' IN BOOLEAN MODE)
LIMIT 3;

Resultado:
Empty set (0.00 sec)

Existem muitos outros operadores que podem ser usados ​​com pesquisas booleanas, como ~ , < , > , * , e mais. Para obter informações mais detalhadas sobre como usar o modo booleano, consulte a documentação do MySQL para pesquisas de texto completo booleano.

Exemplo 9 – Com expansão de consulta cega


Você pode usar o WITH QUERY EXPANSION ou o IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION modificadores para realizar a expansão de consulta cega. Isso pode ser útil quando a frase de pesquisa é muito curta e onde os resultados retornados podem ser muito limitados (excluindo, assim, documentos potencialmente relevantes).

A expansão da consulta pode ampliar a pesquisa retornando linhas que de outra forma não seriam retornadas. Em particular, se uma linha não correspondente contiver palavras que também estão contidas em uma linha correspondente, essa linha não correspondente poderá se tornar uma linha correspondente. Em outras palavras, uma linha não correspondente ainda pode ser retornada, simplesmente porque ela compartilha outras palavras com uma linha correspondente.

Para demonstrar, aqui está uma pesquisa normal sem expansão da consulta:
SELECT AlbumId, AlbumName
FROM Albums
WHERE MATCH(AlbumName) AGAINST('Blue' IN NATURAL LANGUAGE MODE);

Resultado:
+---------+------------+
| AlbumId | AlbumName  |
+---------+------------+
|      13 | Blue Night |
+---------+------------+

Eu declarei explicitamente IN NATURAL LANGUAGE MODE mas este é o modo padrão, então eu também poderia ter omitido este modificador se assim o quisesse.

E aqui está a mesma pesquisa com expansão da consulta:
SELECT AlbumId, AlbumName
FROM Albums
WHERE MATCH(AlbumName) AGAINST('Blue' WITH QUERY EXPANSION);

Resultado:
+---------+-----------------+
| AlbumId | AlbumName       |
+---------+-----------------+
|      13 | Blue Night      |
|      19 | All Night Wrong |
+---------+-----------------+

Nesse caso, dois resultados são retornados. Observe como o segundo resultado não contém a frase de pesquisa (blue ). Mas contém a palavra Night que também está no primeiro resultado. Portanto, a consulta expandida considera isso bom o suficiente para ser uma correspondência.

Os nomes dos álbuns provavelmente não são um bom caso de uso para o modo de expansão de consulta. Um caso de uso melhor pode ser uma pesquisa por, digamos, banco de dados , onde uma consulta expandida também pode retornar documentos que contenham nomes como MySQL , Oráculo , etc, mesmo que não contenham a frase banco de dados .

Aqui está outro exemplo. No entanto, este exemplo usa aspas duplas para especificar que todo o termo de pesquisa deve estar presente.

Se fizermos a pesquisa sem expansão da consulta:
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 |
+------------------+--------------------------------------------------------------------------------------------------+

Apenas um resultado é retornado (é o único resultado que contém a frase inteira, exatamente como digitada).

Mas se usarmos a expansão de consulta cega, eis o que acontece:
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 |
+--------------------+------------------------------------------------------------------------------------------------------+

A primeira linha é a mesma de quando não usamos a expansão de consulta. No entanto, a consulta retorna e retorna linhas que contêm apenas partes do nosso termo de pesquisa. Este resultado está limitado a três apenas porque usei LIMIT 3 . Os resultados reais são muito maiores:
SELECT COUNT(*)
FROM film
WHERE MATCH(title, description) AGAINST('"Feminist And a Mad Scientist"' WITH QUERY EXPANSION);

Resultado:
+----------+
| COUNT(*) |
+----------+
|     1000 |
+----------+

É bem possível que muitos desses resultados sejam completamente irrelevantes para o termo de pesquisa. Portanto, a expansão de consulta cega geralmente funciona melhor para termos de pesquisa mais curtos.

Para obter mais informações sobre como usar a expansão de consulta cega, consulte a documentação do MySQL:Pesquisas de texto completo com expansão de consulta.