Suche mit PHP und MySQL realisieren



  • Hallo, ich möchte eine Suche für meine Seite programmieren. Die Suchbegriffe sollen in einer Datenbank gespeichert werden.

    Kann ich da LIKE verwenden

    Hier ein Beispiel:

    ich gebe "Suchbegriff" ein und in der Datenbankzelle is folgendes gespeichert: "irgendwas, irgendwas2, ..., Suchbegriff, nochwas, ..."

    Kann ich da jetzt mit folgendem das ganze angezeigt bekommen?:

    SELECT * FROM tabelle WHERE suchbegriffe LIKE 'Suchbegriff'



  • Kannst du machen, wird aber wohl nicht allzu effizient sein. Oder habe ich dich falsch verstanden - du willst alle Suchbegriffe in einem einzigen Datensatz speichern?! Fände ich nicht wirklich übersichtlich 😉



  • reichs schrieb:

    SELECT * FROM tabelle WHERE suchbegriffe LIKE 'Suchbegriff'

    Was Suchen in MySQL-Tabellen angeht: Das ist einfach eine Katastrophe! Es wird einzig und allein das Wildcard-Zeichen '%' verwendet (Das was in der Shell das '*' ist). Deine Anfrage sollte also folgendermaßen aussehen:

    SELECT * FROM tabelle WHERE suchbegriffe LIKE '%Suchbegriff%'
    

    Allerdings führt das auch zu Problemen: Gibt der User z.B. "ein" ein. Dann würde die Suche auch bei "Bein", "Kein", "klein" (usw... ) zutreffen.

    Leider ist MySQL in der Beziehung sehr beschränkt. Du müsstest Dir also ein Script bauen, dass Datensätze komplett ausliest und mit Hilfe der Funktionen für Regular-Expressions selbst durchsucht. Bei vielen Datensätzen kann das lange dauern. Da Scripte meistens vom Provider her auf eine maximale Laufzeit von 30 Sekunden beschränkt sind kann es dann eng werden.



  • Gibts für MySQL nicht ein FULLTEXT-Search? Also mit nem ganz normalen SELECT suchen tut man nicht.

    MfG SideWinder



  • Hmmm... Kenne ich nicht. Bin aber auch nicht gerade der MySQL-Spezialist. Melde Dich, falls Du was in der Richtung gefunden hast. Würde mich nämlich auch sehr interessieren.



  • Hallo!

    Im Manual steht einiges dazu: http://dev.mysql.com/doc/mysql/en/fulltext-search.html

    Folgende Sachen sind bei der Volltextsuche in MySQL zu beachten:

    .) Es gibt eine minimale Wortlänge, die in der Konfiguration standardmäßig leider auf 4 Zeichen eingestellt ist. Wörter, die in der Suchanfrage kleiner sind als dieses Limit, werden schlicht ignoriert. Außerdem gibt es eine Stopword-List wo Wörter aufgelistet werden, die in Texten sehr sehr häufig vorkommen w.z.B. 'the','a','in' etc. Meist also englische Wörter, die man gerne auf seine Sprache lokalisieren würde. Diese Wörter werden bei der Suchanfrage gefiltert oder vielleicht überhaupt nicht in den Index aufgenommen. Wenn man keinen Zugriff auf die Konfiguration von MySQL hat, oder wenn der Provider keine ordentlichen Werte für die Volltextsuche definiert hat, dann schaut es äußerst traurig aus was die Anwendung der Volltextsuche in MySQL betrifft.

    .) Wenn man eine Volltext-Suche für mehr als eine Spalte definieren möchte, dann muss man dementsprechend einen FULLTEXT-Index für mehrere Spalten definieren (in phpMyAdmin könnten unerfahrene User Probleme damit haben). Dabei muss man beachten, dass man im MATCH-Operator alle Indices in der Reihenfolge auflistet, wie sie auch in der Erstellung des FULLTEXT-Index aufgezählt wurden.
    Z.B.:
    Zunächst einen Index erstellen:

    ALTER TABLE 'articles' ADD FULLTEXT title_body ('Title' , 'Body' );
    

    Eine einfache Suchanfrage:

    SELECT A_ID, Title, Body
    FROM articles
    WHERE MATCH (Title, Body) AGAINST ('liste der suchwörter');
    

    Wenn wir Body aus der Liste auslassen würden, würde die Suche nicht mehr funktionieren. Normalerweise darf man bei Multiple-Column-Indices die rechts-äußersten Indices progressiv auslassen (also: "col1,col2,col3", "col1,col2", "col1"), aber anscheinend unterstützt MySQL dieses Konzept bei FULLTEXT-Indices nicht (was man im Englischen als "leftmost prefixing" bezeichnet). PhpMyAdmin spuckt bei dieser Query folgenden Fehler aus: "#1191 - Can't find FULLTEXT index matching the column list" :(.

    SELECT A_ID, Title, Body
    FROM articles
    WHERE MATCH (Title) AGAINST ('liste der suchwörter');
    

    .) Die "50% Rauschschwelle": Wenn ein Wort in mehr als 50 % der gefundenen Datensätze vorkommt, dann betrachtet MySQL es als "Rauschwort" und filtert alle Datensätze, die es beinhalten. Das heißt auf Deutsch, wenn ich z.B. 10 Artikel in meiner Datenbank habe, und das Wort "MySQL" in mindestens 5 von denen vorkommt, dann werden diese Artikel bei einer Suchanfrage nach "MySQL" nicht zurückgegeben. Sowas kann nicht immer erwünscht sein, aber man kann dieses Problem mit bool'schen Suchanfragen umgehen:

    SELECT A_ID, Title, Body
    FROM articles
    WHERE MATCH (Title, Body) AGAINST ('liste der suchwörter' IN BOOLEAN MODE);
    

    Wenn wir unsere Suchanfragen nach der Relevanz, die von MySQL gleichzeitig bei der Suche kalkuliert wird, sortieren wollten, dann würde die Query wie folgt aussehen:

    SELECT A_ID, Title, Body, MATCH (Title, Body) AGAINST ('liste der suchwörter' IN BOOLEAN MODE) AS relevance
    FROM articles
    WHERE MATCH (Title, Body) AGAINST ('liste der suchwörter' IN BOOLEAN MODE)
    ORDER BY relevance DESC;
    

    Der Rückgabewert des Match-Operators ist im bool'schen Modus eine ganze Zahl (was der Anzahl der gefundenen Wörter entspricht) und im normalen Modus eine Fließkommazahl, also etwas genauer; nicht nur weil es eine Fließkommazahl ist, sondern weil mehrere Faktoren in die Berechnung dieses Wertes einfließen. Bei bool'schen Suchen in größeren Tabellen, wird es etliche Datensätze mit der selben Relevanz geben, was zur Wirkung haben kann, dass wirklich relevante Texte weit unten in der Ergebnisliste erscheinen würden. Die simpelste Methode das zu ändern, ist, indem wir die Suchanfrage im normalen und im bool'schen Modus durchführen, und die Rückgabewerte zu einem Wert zusammenaddieren:

    SELECT A_ID, Title, Body,
      MATCH (Title, Body) AGAINST ('liste der suchwörter') AS relevance +
      MATCH (Title, Body) AGAINST ('liste der suchwörter' IN BOOLEAN MODE) AS relevance
    FROM articles
    WHERE MATCH (Title, Body) AGAINST ('liste der suchwörter' IN BOOLEAN MODE)
    ORDER BY relevance DESC;
    

    Die Nachteile sind offensichtlich, denn: es wird extra Overhead erzeugt, da jetzt in beiden Modi gesucht werden muss; und komplexe Queries die von bool'schen Operatoren Gebrauch machen, können im normalen Modus teilweise oder ganz ignoriert werden (was nicht unbedingt inakzeptabel sein muss).

    MfG,
    Aziz


Anmelden zum Antworten