Marc Reichelt: MySQL: Suche mit MATCH (...) AGAINST

Hallo an alle,

für ein aktuelles Projekt möchte ich eine einfache Volltextsuche realisieren.
Nun stoß ich auf die Volltext-Suchfunktionen von MySQL, und dachte mir: Das muss es sein!

Soweit, sogut - ich habe also das erste Beispiel von dort ausgeführt. Nun:
Warum wird bei der Suche mit folgendem Query kein Resultat ausgegeben?

SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('mysql');

Eigentlich müssen alle 6 Datensätze gefunden werden - werden aber nicht. Eine Suche nach 'mysqld' funktioniert (1 Datensatz), aber nicht nach 'mysql'. Und: 'mysql' befindet sich nicht in den stopwords.

Was ist da los? Sehe ich den Wald vor lauter Bäumen nicht?

Und: Wie realisiere ich eine UND-Verknüpfung?
Eine Suche mit

SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('tutorial database');

liefert mir drei Resultate, nämlich die, wo 'tutorial' ODER 'database' vorkommen. Ich möchte aber die haben, wo 'tutorial' UND 'database' gefunden werden.
Die boolsche Suche habe ich eben gefunden - ist das meine Lösung? Oder geht es einfacher?

Grüße

Marc Reichelt || http://www.marcreichelt.de/

--
Linux is like a wigwam - no windows, no gates and an Apache inside!
Selfcode: ie:{ fl:| br:> va:} ls:< fo:} rl:( n4:( ss:) de:> js:| ch:? sh:| mo:) zu:)
  1. Hallo Marc,

    Warum wird bei der Suche mit folgendem Query kein Resultat ausgegeben?

    SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('mysql');
    Eigentlich müssen alle 6 Datensätze gefunden werden - werden aber nicht.

    Eben darum findet MySQL nichts - ganz genauso wie es im Handbuch steht.

    Die boolsche Suche habe ich eben gefunden - ist das meine Lösung?

    Ja, das ist Deine Lösung. Siehe ein paar Threads tiefer: meine Antwort im Thread MATCH AGAINST findet nix.

    Oder geht es einfacher?

    Nein.
    @Alexander: Ja, ich finde dieses Verhalten gut.

    Freundliche Grüße

    Vinzenz

    1. Hallo Vinzenz,

      Eben darum findet MySQL nichts - ganz genauso wie es im Handbuch steht.

      Ah ja. Das habe ich glatt übersehen. :-)
      Ich finde das Verhalten gut (auch, wenn es zunächst komisch erscheint) - insbesondere bei großen Datensätzen macht dies wirklich Sinn.

      Die boolsche Suche habe ich eben gefunden - ist das meine Lösung?

      Ja, das ist Deine Lösung. Siehe ein paar Threads tiefer: meine Antwort im Thread MATCH AGAINST findet nix.

      Ah, sehr schön -

      SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('+tutorial +database' IN BOOLEAN MODE);

      führt bei mir zum gewünschten Ergebnis.
      Nun muss ich nur noch die Sucheingabe einlesen, in einzelne Wörter zerlegen und diese auf Gültigkeit (a-z, 0-9) prüfen. :-)

      Grüße & vielen Dank

      Marc Reichelt || http://www.marcreichelt.de/

      --
      Linux is like a wigwam - no windows, no gates and an Apache inside!
      Selfcode: ie:{ fl:| br:> va:} ls:< fo:} rl:( n4:( ss:) de:> js:| ch:? sh:| mo:) zu:)
  2. Hallo nochmals,

    nun habe ich noch ein Problem. Wenn die Suche über MATCH AGAINST erfolgen soll (mit IN BOOLEAN MODE), sollte ein FULLTEXT-Index existieren.
    Soweit an sich kein Problem - aber die Spalten stammen von mehreren Tabellen.

    Ich habe im Beispiel zwei Tabellen.

    Tabelle 1: 'hardware'
    Spalten:
        id bigint(20) unsigned auto_increment primary key,
        name varchar(255) NOT NULL,
        vendor\_id bigint(20) unsigned NOT NULL

    Tabelle 2: 'vendors'
    Spalten:
        id bigint(20) unsigned auto_increment primary key,
        name varchar(255) NOT NULL UNIQUE

    Nun ist 'hardware' zu 'vendors' über 'hardware.vendor_id = vendors.id' verknüpft.
    Ich möchte nun also gewissermaßen einen Index über 'hardware.name' und 'vendors.name' legen. Ist das möglich?

    Beispiel für die Suche:
    Es gibt einen Eintrag mit hardware.name = 'NVIDIA' und vendors.name = 'GeForce 6800 GT'.

    Wenn der Benutzer nun nach 'NVIDIA 6800' sucht, sollte die entsprechende Spalte in der Tabelle 'hardware' gefunden werden.

    Wie realisiere ich diese Suche möglichst einfach und doch performant?
    Ist es vielleicht besser, einen "eigenen Index" in der Tabelle 'hardware' anzulegen, und diesen mitzuführen?

    Grüße

    Marc Reichelt || http://www.marcreichelt.de/

    --
    Linux is like a wigwam - no windows, no gates and an Apache inside!
    Selfcode: ie:{ fl:| br:> va:} ls:< fo:} rl:( n4:( ss:) de:> js:| ch:? sh:| mo:) zu:)