Tobias: Volltextsuche

Hallo,
ich habe vor auf einer Seite die Möglichkeit anzubieten die Homepage zu durchsuchen. Eingesetzt wird MySql als Datenbank und php als serverseite Sprache.

Nun habe ich mir schon einige Methoden angeguckt.

Da wäre MATCH AGAINST - sehr schön und einfach. Nur leider lässt sich da der Suchausdruck nur als ganzes finden und nicht auch als Wortbestandteil.

LIKE scheint je nach DB-Größe nicht sehr performent.

Bei beiden Methoden ist außerdem das Problem, das ich den HTML-Code der u.U. in der Datenbank mit drinsteckt noch rausfiltern muss.

Weiterhin hab ich diese Methode gefunden. Ist das ein üblicher Weg? Gibt es da irgendwo eine vorgefertigte Klasse? Man will ja nicht unbedingt das Rad neu erfinden.

Oder gibt es noch andere, bessere Varianten.

Vielen Dank für eure Hilfe

Tschau

Tobias

--
Speedswimming? Finswimming? Flossenschwimmen?|ie:{ fl:| br:> va:) ls:[ fo:| rl:( n4:° ss:| de:] ch:? mo:) zu:)
Die Erklärung zum Selfcode findest du hier: http://emmanuel.dammerer.at/selfcode.html
Einen Decoder für den Selfcode findest du hier: http://peter.in-berlin.de/projekte/selfcode
  1. Hallo Tobias,

    Bei beiden Methoden ist außerdem das Problem, das ich den HTML-Code der u.U. in der Datenbank mit drinsteckt noch rausfiltern muss.

    das ist Dein Problem.

    Weiterhin hab ich diese Methode gefunden. Ist das ein üblicher Weg?

    üblich ist die Volltextsuche zu nutzen, wenn sie vorhanden ist.
    Der Weg als solcher ist gangbar, wenn man die Stolpersteine entfernt.
    Die dort beschriebene "Komprimierung" ist in meinen Augen unbrauchbar.
    Mir scheint der Beitrag aus der Zeit vor MySQL 4.1 zu stammen.

    Gibt es da irgendwo eine vorgefertigte Klasse? Man will ja nicht unbedingt das Rad neu erfinden.

    Es gibt die Volltextsuche. Klar, die Volltextsuche einer Standard-MySQL-Installation ist für deutsche Texte nicht optimal. Du benötigst eine deutsche Stopwortliste.

    Wenn sie Dir dennoch nicht reicht, dann hast Du spezifische Ansprüche.

    Dein "HTML-Problem" kannst Du übrigens damit beheben, dass Du in einer weiteren Spalte den ums Markup bereinigten Text speicherst, falls Du das für sinnvoll erachtest. Ein paar Hinweise:

    - strip_tags ist eine grobe Wildsau
     - möchtest Du eventuell Attribut-Inhalte erhalten, z.B. von alt-Attributen.
     - stripslashes() auf Datenbankinhalte? Warum? Fast immer ein Fehler.
     - Umwandlung von Nicht-ASCII-Zeichen?
       Nein, nutze die entsprechende Kollation.

    Was der Artikel richtig angibt: je nach Datenquelle gilt es, die unterschiedlich zu behandeln. Ziehe Deinen Schluss auf "vorgefertigte Klassen".

    Freundliche Grüße

    Vinzenz

    1. Hallo Vinzenz,

      Die dort beschriebene "Komprimierung" ist in meinen Augen unbrauchbar.
      Mir scheint der Beitrag aus der Zeit vor MySQL 4.1 zu stammen.

      könntest du das etwas näher Erläutern, warum sie in deinen Augen unbrauchbar ist?

      Tschau

      Tobias

      --
      Speedswimming? Finswimming? Flossenschwimmen?|
      ie:{ fl:| br:> va:) ls:[ fo:| rl:( n4:° ss:| de:] ch:? mo:) zu:)
      Die Erklärung zum Selfcode findest du hier: http://emmanuel.dammerer.at/selfcode.html
      Einen Decoder für den Selfcode findest du hier: http://peter.in-berlin.de/projekte/selfcode
      1. Hallo Tobias,

        Die dort beschriebene "Komprimierung" ist in meinen Augen unbrauchbar.
        Mir scheint der Beitrag aus der Zeit vor MySQL 4.1 zu stammen.

        könntest du das etwas näher Erläutern, warum sie in deinen Augen unbrauchbar ist?

        hab' ich das nicht schon getan:

        • strip_tags ist eine grobe Wildsau
        • möchtest Du eventuell Attribut-Inhalte erhalten, z.B. von alt-Attributen.
        • stripslashes() auf Datenbankinhalte? Warum? Fast immer ein Fehler.
        • Umwandlung von Nicht-ASCII-Zeichen?
             Nein, nutze die entsprechende Kollation.

        vergleiche das mit den fünf Listenpunkten der dortigen Komprimierung:

        *  HTML-Tags entfernen (strip_tags())
        nein, das will man nicht, siehe meine beiden ersten Punkte.

        * Slashe entfernen (stripslashes())

        Das will man erst recht nicht. Was sollen irgendwelche Slashes in Datenbankinhalten. Da sollten keine Slashes drin sein, die man nicht ganz speziell haben will.

        * Leerzeichen entfernen (trim())
        das wird vermutlich wenig schaden, aber auch nicht viel nutzen.

        * In Kleinbuchstaben umwandeln (strtolower())
        wie wäre es mit einer ci-Kollation (ci wie case insensitive). Also überflüssig, siehe letzte meiner Anmerkungen.

        * Sonderzeichen umwandeln und entfernen
        Warum in aller Welt das. Nein, natürlich nicht. Es verfälscht die Suchergebnisse. Selbstverständlich will ich diese normalen Zeichen meiner Sprache erhalten, damit ich ganz gezielt nach Wörtern suchen kann, die diese enthalen. Außerdem kann ich eine Kollation verwenden, die z.B. ß und ss als gleich ansieht.

        MySQL 4.1 brachte enorme Fortschritte bei Zeichencodierung und Kollation. Deswegen meine Vermutung, dass ein Teil der Prinzipien dieser "Komprimierung" aus der Zeit vor MySQL 4.1 stammt.

        Bleibt als einzig nicht besonders schädliche Maßnahme das Trimmen.

        Nochmals: wenn die Volltextsuche angemessen konfiguriert ist, will man diese verwenden. Dazu kommt die Ineffizienz der Suche, die je zusätzlichem Suchwort zwei zusätzliche Selfjoins über nicht gerade kleine Tabellen hinzufügt - eine Performancebremse erster Güte. Das Nichtverwenden von Subselects deutet ebenfalls auf die Zeit vor MySQL 4.1 hin.

        Statt dieser Selfjoins könnte man die Strategien 2) und 3) dieses Archivbeitrags von mir verwenden. Es bleibt, dass diese Suche *nicht* skaliert.

        Freundliche Grüße

        Vinzenz

        1. Hallo Vinzenz,

          hab' ich das nicht schon getan:

          sorry irgendwie hab ich den Teil wohl in einem anderem Kontext gesehen. Vielen Dank für dein ausführliche Erklärung.

          Nochmals: wenn die Volltextsuche angemessen konfiguriert ist, will man diese verwenden.

          Ich will sie ja sehr gerne verwenden. Nur schein ich an dem "angemessen konfigurieren" zu scheitern. Ok, das HTML-Zeugs kann ich noch irgendwie hinterher rausfiltern. Aber eben, dass man nach wortbestandteilen Suchen kann krieg ich nicht hin. Mit dem Boolean-Mode hab ich ja nur die halbe Miete, da dort ja nur die Möglichkeit besteht Wörter zu finden bei dem das Suchwort am Anfang steht, nicht jedoch mittendrin oder gar zum Schluss.

          Tschau

          Tobias

          --
          Speedswimming? Finswimming? Flossenschwimmen?
          ie:{ fl:| br:> va:) ls:[ fo:| rl:( n4:° ss:| de:] ch:? mo:) zu:)
          Die Erklärung zum Selfcode findest du hier: http://emmanuel.dammerer.at/selfcode.html
          Einen Decoder für den Selfcode findest du hier: http://peter.in-berlin.de/projekte/selfcode
  2. Hallo Tobias.

    Wenn du das Rad nicht neu erfinden willst, kannst du z.B. Zend_Search_Lucene einsetzen, (das ist ein Teil des Zend-Frameworks).

    Damit sparst du dir viel Arbeit, die du zum Teil aber dafür verwenden werden musst, um dich mit Zend_Search_Lucene vertraut zu machen.

    Servus,
    Flo

    1. Hallo flowh,
      vielen Dank für den Tipp. Ich überlege schon eine ganze Weile mir Zend endlich mal zu Gemüte zu führen. Bisher hab ich mich da aber noch nicht so richtig rangetraut.

      Derzeit hab ich leider nicht so richtig Zeit dafür :(

      Tschau

      Tobias

      --
      Speedswimming? Finswimming? Flossenschwimmen?
      ie:{ fl:| br:> va:) ls:[ fo:| rl:( n4:° ss:| de:] ch:? mo:) zu:)
      Die Erklärung zum Selfcode findest du hier: http://emmanuel.dammerer.at/selfcode.html
      Einen Decoder für den Selfcode findest du hier: http://peter.in-berlin.de/projekte/selfcode
      1. Hallo Tobias.

        Du musst die gar nicht das Zend Framework als Ganzes zu Gemüte führen, die meisten Teile lassen sich als eigenständige Klassen super verwenden.

        Du müsstest wirklich nur mit Zend_Search_Lucene etc. auseinandersetzen.

        Servus,
        Flo