sql >> Databasteknik >  >> RDS >> Mysql

Hur MATCH()-funktionen fungerar i MySQL

I MySQL, MATCH() funktionen utför en fulltextsökning. Den accepterar en kommaseparerad lista med tabellkolumner som ska sökas i.

Tabellen/tabellerna måste ha en FULLTEXT indexera innan du kan göra en fulltextsökning mot dem (även om booleska frågor mot en MyISAM sökindex kan fungera – om än långsamt – även utan en FULLTEXT index).

Du kan skapa en FULLTEXT index när du skapar tabellen (med hjälp av CREATE TABLE uttalande), eller så kan du använda ALTER TABLE eller CREATE INDEX uttalande om tabellen redan finns.

Som standard är sökningen skiftlägesokänslig. För att utföra en skiftlägeskänslig sökning, använd en skiftlägeskänslig eller binär sammanställning för de indexerade kolumnerna.

Syntax

Syntaxen för MATCH() funktionen går så här:

MATCH (col1,col2,...) AGAINST (expr [search_modifier])

Där col1,col2,... är den kommaseparerade listan över kolumner att söka i, och expr är inmatningssträngen/uttrycket.

Den valfria search_modifier argument låter dig ange söktypen. Det kan vara något av följande värden:

  • I NATURLIGT SPRÅKSLÄGE
  • I NATURLIGT SPRÅKLÄGE MED FRÄGEEXPANSION
  • I BOOLENSK LÄGE
  • Med QUERY EXPANSION

Standardläget är I NATURAL LANGUAGE LÄGE .

Exempel 1 – Grundläggande användning

Här är ett exempel på hur du använder den här funktionen:

SELECT AlbumId, AlbumName
FROM Albums
WHERE MATCH(AlbumName) AGAINST('cool');

Resultat:

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

Här är den fullständiga tabellen som ovanstående fråga kördes mot:

SELECT AlbumId, AlbumName
FROM Albums;

Resultat:

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

Exempel 2 – Fel:"Kan inte hitta FULLTEXT-index"

InnoDB tabeller måste ha en FULLTEXT indexera innan det returnerar resultat från en fulltextsökning. Om den inte har en FULLTEXT index kommer du troligen att få följande felmeddelande:

ERROR 1191 (HY000): Can't find FULLTEXT index matching the column list

Om du får det felet måste du lägga till en FULLTEXT index för alla kolumner som du försöker söka i (se nästa exempel).

Undantaget från detta kan vara om du kör en boolesk fråga mot en MyISAM sökindex.

För att vara mer specifik anger MySQL-dokumentationen för booleska fulltextsökningar följande:

InnoDB tabeller kräver en FULLTEXT index på alla kolumner i MATCH() uttryck för att utföra booleska frågor. Booleska frågor mot en MyISAM sökindex kan fungera även utan en FULLTEXT index, även om en sökning som utförs på detta sätt skulle vara ganska långsam.

Exempel 3 – Lägga till ett FULLTEXT-index till en befintlig tabell

Här är ett exempel på hur du lägger till en FULLTEXT indexera till en befintlig tabell:

ALTER TABLE Albums  
ADD FULLTEXT(AlbumName);

I det här fallet indexerade jag innehållet i AlbumName kolumn.

För att indexera flera kolumner, separera dem med ett kommatecken (se nästa exempel).

Exempel 4 – Söka i flera kolumner

Om du tror att du behöver söka i mer än en kolumn måste du skapa ett index som inkluderar alla kolumner som ska sökas i. För att göra detta, inkludera helt enkelt varje kolumn som en kommaseparerad lista.

Här är ett exempel där jag lägger till en FULLTEXT indexera till filmen tabell (som är en del av Sakila exempeldatabas).

ALTER TABLE film 
ADD FULLTEXT(title, description);

I det här fallet indexerar jag innehållet i titeln och beskrivning kolumner.

Nu när vi har skapat en FULLTEXT index för båda kolumnerna kan vi göra en fulltextsökning mot dem:

SELECT title, description
FROM film
WHERE MATCH(title, description) AGAINST('vertigo');

Resultat:

+-------------------+-----------------------------------------------------------------------------------------------------------+
| title             | description                                                                                               |
+-------------------+-----------------------------------------------------------------------------------------------------------+
| VERTIGO NORTHWEST | A Unbelieveable Display of a Mad Scientist And a Mad Scientist who must Outgun a Mad Cow in Ancient Japan |
+-------------------+-----------------------------------------------------------------------------------------------------------+

Här är en annan sökning, där den exakta nyckelfrasen inte matchar, men varje sökord i den frasen gör det:

SELECT title, description
FROM film
WHERE MATCH(title, description) AGAINST('Iron Maiden');

Resultat:

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

Om du bara vill att den exakta frasen ska matcha, placera dubbla citattecken runt den:

SELECT title, description
FROM film
WHERE MATCH(title, description) AGAINST('"Iron Maiden"');

Resultat:

Empty set (0.00 sec)

I det här fallet innehåller ingen av kolumnerna den exakta frasen.

Exempel 5 – Returnera relevanspoängen

När du använder MATCH() funktion tilldelas varje rad i tabellen ett relevansvärde. Med andra ord får varje rad en poäng som avgör hur relevant den är för söktermen. Resultaten sorteras sedan efter relevans (högsta relevans först).

Relevansvärden är icke-negativa flyttal. Noll relevans betyder ingen likhet. Relevans beräknas baserat på antalet ord i raden (dokumentet), antalet unika ord i raden, det totala antalet ord i samlingen och antalet rader som innehåller ett visst ord.

För att returnera relevansen för varje resultat, inkludera helt enkelt MATCH() funktion i din lista över kolumner för att välja.

Exempel:

SELECT 
  MATCH(title, description) AGAINST('Iron Maiden') AS Relevance,
  title, 
  description
FROM film
WHERE MATCH(title, description) AGAINST('Iron Maiden');

Resultat:

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

I det här fallet är relevanspoängen mycket hög för båda raderna.

Här är en annan där relevansen är lägre:

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;

Resultat:

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

Observera att resultatuppsättningen skulle ha varit mycket större om jag inte hade använt LIMIT 15 för att begränsa antalet resultat till 15.

Exempel 6 – Returnerar endast resultat över ett visst relevanspoäng

Vi kan ta det föregående exemplet ett steg längre och filtrera bort endast de resultat med en viss relevanspoäng. I det här fallet specificerar jag att relevanspoängen måste vara högre än 2.

Var dock försiktig när du gör detta. Som framgår ovan kan relevansvärdena vara mycket höga eller mycket låga, beroende på faktorer som hur mycket text som finns i kolumnen, hur många andra rader som matchar söktermen, 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;

Resultat:

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

Exempel 7 – Inkludera nollrelevansresultat

Här är ett exempel på att lista ut relevansvärdena för varje rad, även om relevansvärdet är noll. Vi kan göra detta genom att inte använda MATCH() funktion i WHERE klausul.

I det här exemplet använder jag faktiskt inte en WHERE klausul. Jag använder bara en LIMIT klausul för att begränsa antalet resultat.

SELECT 
  MATCH(title, description) AGAINST('Scientist') AS Relevance,
  title, 
  description
FROM film
LIMIT 15;

Resultat:

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

Exempel 8 – Boolean Mode

MySQL låter oss köra fulltextsökningar i booleskt läge. För att göra detta, lägg till I BOOLENSK LÄGE modifierare till din fråga.

Booleskt läge låter dig använda operatorer som + och - för att ange om ett visst ord eller en viss fras måste eller inte får finnas.

I följande exempel prefixar jag varje ord med ett plustecken (+ ) för att indikera att båda orden måste finnas.

SELECT 
  title, 
  description
FROM film
WHERE MATCH(title, description) AGAINST('+Saga +Moose' IN BOOLEAN MODE)
LIMIT 3;

Resultat:

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

I nästa exempel ändrar jag ett av plustecknen till ett minustecken (- ). Det betyder att endast de rader som innehåller ordet Saga kommer att returneras, men bara om de inte gör det innehåller även Älg :

SELECT 
  title, 
  description
FROM film
WHERE MATCH(title, description) AGAINST('+Saga -Moose' IN BOOLEAN MODE)
LIMIT 3;

Resultat:

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

Minustecknet används för att utesluta resultat som annars skulle returneras. Därför, om alla våra sökord har ett minustecken prefix, returneras en tom uppsättning.

SELECT 
  title, 
  description
FROM film
WHERE MATCH(title, description) AGAINST('-Saga -Moose' IN BOOLEAN MODE)
LIMIT 3;

Resultat:

Empty set (0.00 sec)

Det finns många fler operatorer som kan användas med booleska sökningar, såsom ~ , < , > , * , och mer. För mer detaljerad information om hur du använder booleskt läge, se MySQL-dokumentationen för booleska fulltextsökningar.

Exempel 9 – Med Blind Query Expansion

Du kan använda WITH QUERY EXPANSION eller I NATURAL LANGUAGE-LÄGE MED FRÄGEEXPANSION modifierare för att utföra blinda frågeexpansion. Detta kan vara användbart när sökfrasen är mycket kort, och där resultaten som returneras kan vara för snäva (därmed utesluter potentiellt relevanta dokument).

Frågeexpansion kan bredda sökningen genom att returnera rader som annars inte skulle returneras. I synnerhet, om en icke-matchande rad innehåller ord som också finns i en matchande rad, kan den icke-matchande raden bli en matchande rad. Med andra ord kan en rad som inte matchar fortfarande returneras, helt enkelt för att den delar andra ord med en matchande rad.

För att demonstrera, här är en normal sökning utan frågeexpansion:

SELECT AlbumId, AlbumName
FROM Albums
WHERE MATCH(AlbumName) AGAINST('Blue' IN NATURAL LANGUAGE MODE);

Resultat:

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

Jag angav uttryckligen I NATURAL LANGUAGE LÄGE men detta är standardläget, så jag kunde också ha utelämnat den här modifieraren om jag hade valt det.

Och här är samma sökning med frågeexpansion:

SELECT AlbumId, AlbumName
FROM Albums
WHERE MATCH(AlbumName) AGAINST('Blue' WITH QUERY EXPANSION);

Resultat:

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

I det här fallet returneras två resultat. Lägg märke till hur det andra resultatet inte innehåller sökfrasen (blå ). Men det innehåller ordet Natt vilket också råkar vara i det första resultatet. Så den utökade frågan anser att det är tillräckligt bra för att vara en matchning.

Albumnamn är förmodligen inte ett särskilt bra användningsfall för frågeexpansionsläge. Ett bättre användningsfall kan vara en sökning efter säg, databas , där en utökad fråga också kan returnera dokument som innehåller namn som MySQL , Oracle , etc även om de inte innehåller frasen databas .

Här är ett annat exempel. Det här exemplet använder dock dubbla citattecken för att specificera att hela söktermen ska finnas med.

Om vi ​​gör sökningen utan frågeexpansion:

SELECT 
  title, 
  description
FROM film
WHERE MATCH(title, description) AGAINST('"Feminist And a Mad Scientist"')
LIMIT 3;

Resultat:

+------------------+--------------------------------------------------------------------------------------------------+
| title            | description                                                                                      |
+------------------+--------------------------------------------------------------------------------------------------+
| ACADEMY DINOSAUR | A Epic Drama of a Feminist And a Mad Scientist who must Battle a Teacher in The Canadian Rockies |
+------------------+--------------------------------------------------------------------------------------------------+

Endast ett resultat returneras (det är det enda resultatet som innehåller hela frasen, exakt som det skrivits).

Men om vi använder blindfrågeexpansion händer det här:

SELECT 
  title, 
  description
FROM film
WHERE MATCH(title, description) AGAINST('"Feminist And a Mad Scientist"' WITH QUERY EXPANSION)
LIMIT 3;

Resultat:

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

Den första raden är samma som när vi inte använde frågeexpansion. Men frågan går sedan och returnerar rader som bara innehåller delar av vår sökterm. Detta resultat är begränsat till tre bara för att jag använde LIMIT 3 . De faktiska resultaten är mycket bättre:

SELECT COUNT(*)
FROM film
WHERE MATCH(title, description) AGAINST('"Feminist And a Mad Scientist"' WITH QUERY EXPANSION);

Resultat:

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

Det är mycket möjligt att många av dessa resultat är helt irrelevanta för söktermen. Därför fungerar blind sökning oftast bäst för kortare söktermer.

För mer information om hur du använder blindfrågeexpansion, se MySQL-dokumentationen:Full-Text Searches with Query Expansion.


  1. Förbättra partitionsunderhåll med inkrementell statistik

  2. Skapa valfria beroenden

  3. Hur man skapar en tabell i SQL – Postgres och MySQL Exempelfråga

  4. Vad är det bästa sättet att automatiskt generera INSERT-satser för en SQL Server-tabell?