Maximilian Weber: Volltextsuche

hallo,

ich habe soeben eine volltextsuche in php realisiert.

mein vorgehen dabei ist folgendes:
ich lasse mir den inhalt der datensätz per

WHERE MATCH seiteninhalt AGAINST ('+".$suchwort."' IN BOOLEAN MODE)";

ausgeben.

danach überprüfe ich mit

preg_replace("/((<[^>]*)|$s)/ie", '"\2"=="\1"? "\1":"<b>\1</b>"', $seiteninhalt)

, ob das suchwort tatsächlich im text und nicht im quelltext der zu durchsuchenden Seiten vorkommt.

Das ist aber sehr ineffizient. denn wenn jemand nach "table" sucht sind praktisch alle datenbankeinträge treffer, aber nur ein bruchteil beinhaltet "table" im "sichtbaren" text! trotzdem muss quasi die gesamte datenbank "geladen" werden.

Ist es nicht möglich, den verwendeten regulären ausdruck bereits in der mysql-abfrage zu verwenden?

Oder wäre gar ein ganz anderes vorgehen ratsamer, das ich nicht kenne?

VIELEN DANK,
maxi

  1. hi,

    Ist es nicht möglich, den verwendeten regulären ausdruck bereits in der mysql-abfrage zu verwenden?

    Das wird wohl kaum performanter sein.

    Oder wäre gar ein ganz anderes vorgehen ratsamer, das ich nicht kenne?

    Du könntest den Inhalt in zwei Versionen in der Datenbank ablegen, mit und ohne den HTML-Code - und durchsuchen tust du dann die Version ohne.

    Das beinhaltet zwar eine gewisse Redundanz der Daten - aber die muss man manchmal auch in Kauf nehmen, wenn man bessere Performance will.

    gruß,
    wahsaga

    --
    /voodoo.css:
    #GeorgeWBush { position:absolute; bottom:-6ft; }
    1. die zweite idee ist gar nicht schlecht.

      ich müsste mir dann hald ein script schreiben, welches ab und an beide "versionen" synchronisiert, dann muss ich nicht das gesamte projekt umprogrammieren (mehrsprachig...)

      weiß jemand wie man das generell realisiert in großen cms zum beispiel?
      den inhaltlichen text kann man ja nie vollständig vom inhalt lösen, arbeiten solche systeme dann mit einem filter, welcher html tags verbietet? und wenn ja stellt sich mir die frage, wie zum beispiel das problem gelöst wird, dass ja zahlen im quelltext vorkommen können???

      ist so eine filterung nach html-tags üblich? wie würde das ein englisches möbelhaus realisieren, das tische verkauft???

      1. Solche Systeme arbeiten zumeist mit einem Templatesystem, dass den Einbau von großen HTML-Blöcken umgeht.
        Eventuell lässt sich etwas derartiges bei dir auch realisieren.

        1. Solche Systeme arbeiten zumeist mit einem Templatesystem, dass den Einbau von großen HTML-Blöcken umgeht.
          Eventuell lässt sich etwas derartiges bei dir auch realisieren.

          Selbstverständlich verwende auch ich ein templatesystem ;)

          allerdings ist das cms eine gewerbliche seite, welche waren anbietet. dabei werden jedes jahr aufs neue 200-300 html seiten generiert (golive) welche dann automatisch in das system eingelsen werden, wo sie dann "on-the-fly" bearbeitet werden können. dieses vorgehen wurde gewählt, weil sich die produktpalette jährlich stark verändert. nun finden sich aber in den seiten "html-formatierungen" ohne ende- von der tabelle bis zum kursiv-tag. ich weiß nicht, wie sich das trennen ließe. mein template system ist smarty.

          die suchfunktion ist für die kunden extrem wichtig, die seite ist hochfrequentiert, wahrscheinlich muss ich tatsächlich eine möglichkeit finden, html, css (und evtl. javascript) tags ls suchbegriffe zu verbieten!

          hat jemand eine idee?

          1. Je nach Umfang deiner Datenbank bietet es sich sowieso an, den Index auszulagern und nicht bei jeder kleinen Änderung zu aktualisieren. Dann kannst du für diesen das ganze HTML sparen und nur den Text ablegen, wie es bereits vorgeschlagen wurde.

            1. Je nach Umfang deiner Datenbank bietet es sich sowieso an, den Index auszulagern und nicht bei jeder kleinen Änderung zu aktualisieren. Dann kannst du für diesen das ganze HTML sparen und nur den Text ablegen, wie es bereits vorgeschlagen wurde.

              wie geht man da am besten vor?

              vermutlich wäre es sinnvoll beim anlegen dieses ausgelagerten indexes gleich noch alle worte wie "ist, bei, im,..." etc zu löschen??

              gibt es für soetwas fertige funktionen, oder soll ich damit rechnen einen weiteren nachmittag zu "opfern"?

              1. Ich kenne die Funktionsweise des Indexes leider selbst nicht genau, aber ich glaube das ist für deine Zwecke nicht notwendig, da MySQL eigene Filter besitzt
                Eine mögliche Herangehensweise wäre die folgende:

                Einmal am Tag liest du per CronJob sämtliche Einträge deiner eigentlichen Datenbank aus. Hier lassen sich durch verschiedenste Algorithmen Performance-Einsparungen verwirklichen. Der Klassiker wäre: Ein timestamp-Abgleich der letzten Änderung.

                Alle für dein Programm erkennbar geänderten DB-Einträge werden nun in eine zweite Tabelle übertragen. Gespiegelt werden müssen natürlich nur die durchsuchbaren Felder und der Identifier (i.d.R. der primary_key). Wenn jemand nun eine Suche startet wird deine SELECT-Anweisung auf die Tabelle mit Fulltext-Index umgeleitet. Du fragst also die eigentlich fremde Tabelle ab.

                Treffer hier können dann auch als Treffer in der eigentlichen Datenbank betrachtet werden. Diesen "echten" Eintrag rufst du dann auch auf, wenn dein SELECT mit einer eindeutigen Auswahl durchgeführt werden kann: "SELECT * FROM xyz WHERE primary_key = 123" statt "SELECT * FROM xyz_mit_fulltext WHERE MATCH (feld) AGAINST (suche)"

                Um zum Beispiel vorzubeugen, dass gelöschte Einträge noch in der Suche austauschen könntest du noch durch einen JOIN der eigentlichen Tabelle in deine Fulltext-Tabelle unterbinden.
                (z.B. "SELECT A.* FROM xyz_mit_fulltext AS A WHERE MATCH (A.feld) AGAINST (suche) INNER JOIN xyz AS B ON A.primary_key = B.primary_key")
                Viel Erfolg bei der Umsetzung.

                1. so langsam gefällt mir die idee recht gut!

                  (was sind aber cron jobs?)

                  VIELEN DANK, werdet demnächst dann wieder von mir hören, werde mich einmal darum kümmern, das ganze soweit wie möglich so umzusetzen, wie empfohlen, danke nochmal!

                  1. was sind aber cron jobs?

                    Ein CronJob ist sowas wie ein automatischer Prozess.
                    http://de.wikipedia.org/wiki/Cron.

                    Du könntest also eine PHP-Seite anlegen, die dann von deinem CronTab alle drei Tage ausgeführt wird und den Index umschreibt. Bei "großen Aufgaben" lohnt es sich eventuell den Job in verschiedene Schrite auszulagern, um die maximale Laufzeit nicht zu überschreiten.

                    Grüße.

  2. wen es interessiert:

    mein projekt ist relativ interessant, weil für meine verhältnisse recht umfangreich.

    http://www.berk-esoterik.de

    danke für euer interesse an meinen problemchen!