sql >> Databasteknik >  >> RDS >> Mysql

Fulltextsökningar i MySQL:The Good, the Bad and the Ugly

Ibland när du söker i en MySQL-databas kanske du vill köra fulltextsökningar mot teckenbaserade data. Idag diskuterar vi fördelarna och nackdelarna med sådana sökmetoder.

Vad är fulltextsökningar i MySQL?

Fulltextsökning är en teknik som gör att du kan söka efter poster som kanske inte helt matchar sökkriterierna. Fulltextsökningar i MySQL utförs när vissa index används och dessa index har många unika nyanser inklusive följande:

  • För att indexet ska betraktas som ett fulltextindex måste indexet vara av typen FULLTEXT.
  • FULLTEXT-index kan endast användas på tabeller som kör lagringsmotorerna InnoDB eller MyISAM.
  • FULLTEXT-index kan endast skapas för CHAR-, VARCHAR- eller TEXT-kolumner.
  • FULLTEXT-index används endast när MATCH() AGAINST()-satsen används.
  • Fulltextsökningar har tre lägen:det naturliga språkläget, det booleska läget och frågeexpansionsläget.

Ett FULLTEXT-index är en speciell typ av index som hittar nyckelord i texten istället för att jämföra värdena med värdena i indexet. Även om FULLTEXT-sökning skiljer sig från andra typer av matchning, notera att du kan ha ett BTREE-index och ett FULLTEXT-index på samma kolumn samtidigt - de kommer inte att komma i konflikt eftersom de är lämpade för olika ändamål.

Söktyper i fulltext

När du kör fulltextsökningar i MySQL, kom ihåg att det finns tre söktyper att välja mellan:

  1. En söktyp för naturligt språk - ett sådant sökläge tolkar söksträngen som en bokstavlig fras. Aktiverad som standard om ingen modifierare har angetts eller när modifieraren I NATURAL LANGUAGE MODE är specificerad;
  2. En söktyp för utökad sökning - ett sådant sökläge utför sökningen två gånger. Vid andra sökningen innehåller resultatuppsättningen några av de mest relevanta dokumenten från den första sökningen. Aktiverad med modifieraren WITH QUERY EXPANSION;
  3. En boolesk söktyp – ett sådant sökläge gör det möjligt att söka efter komplexa frågor som kan inkludera booleska operatorer som mindre än (“<”) och fler än (“>”) operatorer, subexpressions (“( ” och “)”), plustecknet (+), minustecknet (-), dubbla citattecken (“”), en operator som sänker värdets bidrag till resultaten (~) och jokerteckenoperatören (*) - den jokerteckenoperatören tillåter sökning med fuzzy matchning (till exempel "demo*" skulle också matcha "demonstration"). Aktiverad med modifieraren IN BOOLEAN MODE.

Fulltextsökningar med Natural Language Search Mode

Ett sökläge för naturligt språk, som nämnts ovan, är aktiverat som standard eller när modifieraren IN NATURAL LANGUAGE MODE är specificerad. Detta läge utför en naturlig språksökning mot en given textsamling (en eller flera kolumner). Det grundläggande frågeformatet för fulltextsökningar i MySQL bör likna följande:

SELECT * FROM table WHERE MATCH(column) AGAINST(“string” IN NATURAL LANGUAGE MODE);

När MATCH() används tillsammans med en WHERE-sats, sorteras raderna automatiskt efter högsta relevans först. För att söka efter en exakt sträng, omslut den med dubbla citattecken.

Fulltextsökningar med läget Query Expansion

Fulltextsökningar stöder också läget för utökning av frågor. Ett sådant sökläge används ofta när användaren förlitar sig på underförstådd kunskap - till exempel kan användaren söka efter "DBMS" i hopp om att se både "MongoDB" och "MySQL" i sökresultaten. Anledningen till att användaren kanske kan förlita sig på viss underförstådd kunskap när han använder ett sådant sökläge är ganska enkel - en fulltextsökning med sökningsexpansionsläget fungerar genom att utföra sökningen två gånger:den andra sökfrasen är den första sökfrasen sammanlänkade med några mest relevanta poster från den första sökningen. Det betyder att, till exempel, om i den första sökningen en av raderna skulle innehålla ordet "DBMS" och ordet "MySQL", skulle den andra sökningen hitta de poster som skulle innehålla ordet "MySQL" även om de inte gör det innehåller "DBMS". Frågeformatet som skulle använda frågeexpansionsläget skulle se ut så här:

SELECT * FROM table WHERE MATCH(column) AGAINST(“string” WITH QUERY EXPANSION); 

Fulltextsökningar med booleskt läge

Det booleska läget är kanske en av de mest intressanta sakerna som MySQL fulltextsökning har att erbjuda. Det här läget har många varningar som är unika för det eftersom det låter dig utöka sökmöjligheterna med hjälp av booleska operatorer. När det booleska läget används kan vissa tecken ha speciell betydelse i början eller slutet av ord. Till exempel:

  • "+" betyder OCH;
  • “-” betyder INTE;
  • Operatorerna "(" och ")" gör det möjligt att skapa underuttryck;
  • "<" och ">"operatorerna ändrar rankningen av sökvärdet lägre eller högre;
  • “~” sänker värdets bidrag till sökresultaten;
  • Dubbelcitattecken (“”) matchar endast bokstavliga värden;
  • “*” är en jokerteckenoperatör (se förklaringen ovan).

Dessa operatorer låter dig utöka sökningens funktionalitet:om du till exempel vill hämta alla rader som innehåller ordet "Demo", men inte "Demo2", kan du använda en fråga som så:

SELECT * FROM table WHERE MATCH(column) AGAINST (“+Demo -Demo2” IN BOOLEAN MODE);

Du kan också använda dubbla citattecken tillsammans med enkla citattecken som så:

SELECT * FROM table WHERE MATCH(column) AGAINST(‘“search string”’ IN BOOLEAN MODE);

Full-Text Search Gotchas

Innan du använder fulltextsökning i MySQL, kom ihåg att sökningen har några "gotchas":

  • Både lagringsmotorerna InnoDB och MyISAM har sina egna listor med stoppord. InnoDB stoppordslista hittar du här, MyISAM stoppordslista hittar du här.
    • För att definiera din egen stoppordslista för InnoDB, definiera en tabell med samma struktur som tabellen INNODB_FT_DEFAULT_STOPWORD, infoga stoppord där och ställ sedan in värdet för alternativet innodb_ft_server_stopword_table i form av db_name/tabellnamn.
    • För att definiera din egen stoppordslista för MyISAM, ställ in variabeln ft_stopword_file till sökvägsnamnet för filen som innehåller stoppordslistan. I filen kan stoppord separeras med valfritt icke-alfanumberiskt tecken förutom "_" och "'". Standardstoppordsfilen finns på storage/myisam/ft_static.c. Stoppord kan inaktiveras genom att ställa in variabeln till en tom sträng.
  • Fulltextsökningar stöds inte på partitionerade tabeller.
  • Alla kolumner i ett FULLTEXT-index måste använda samma teckenuppsättning och sortering.
  • Fulltextsökningar behandlar inte %-strängen som ett jokertecken.

Här är en annan hake:du kanske också vill ha i åtanke att den inbyggda FULLTEXT-tolkaren bestämmer var ord börjar och slutar genom att titta på vissa tecken inklusive mellanslag (“ “), kommatecken (“, ”) och punkt (“.”) vilket betyder att om din söksträng innehåller ett eller flera av dessa tecken kanske sökresultaten inte är korrekta. Till exempel, om din databas innehåller 5 rader med strängen "test.demo", kan sökfrågan "test.demo" returnera fler (10, 15 etc.) resultat inklusive "demo", "string.demo_example" etc. eftersom den kommer att söka efter "demo" istället för "test.demo", så du kan ha fastnat med många irrelevanta matchningar. MySQL erbjuder en lösning för det här problemet om du är villig att skriva ditt eget plugin i C eller C++ (se MySQL-dokumentationen), men tills dess kan du inte göra mycket.

Den fullständiga listan över MySQL:s fulltextbegränsningar kan ses på MySQL:s dokumentationssida.

Sammanfattning

MySQL fulltextsökfunktion ger ett enkelt sätt att implementera olika söktekniker (naturligt språksökning, sökexpansionssökning och boolesk sökning) i din applikation som kör MySQL. Var och en av dessa söktekniker har sina egna varningar och var och en av dem kan vara lämpade för olika ändamål - när du bestämmer dig för om du ska använda fulltextsökning, kom ihåg att denna typ av sökning har många finesser som är unika för sig själv, känner till både fördelarna och nackdelar med att använda fulltextsökning i MySQL och välja klokt.


  1. Hur WEEK() fungerar i MariaDB

  2. SQL-fråga för att hitta saknade rader mellan två relaterade tabeller

  3. Oracle ORA-12154-fel på lokal IIS, men inte med Visual Studio Development Server

  4. Hur använder man ANY istället för IN i en WHERE-klausul med Rails?