Frage

Ich habe ein Problem bei der Webanwendungsentwicklung, für das ich eine Lösung entwickelt habe, versuche aber, andere Ideen zu finden, die einige meiner Leistungsprobleme umgehen könnten.

Problemstellung:

  • Ein Benutzer gibt mehrere Schlüsselwörter/Tokens ein
  • Die Anwendung sucht nach Übereinstimmungen mit den Token
  • Ich benötige ein Ergebnis für jedes Token
    • Das heißt, wenn ein Eintrag 3 Token hat, benötige ich die Eintrags-ID dreimal
  • Ordnen Sie die Ergebnisse
    • Weisen Sie X Punkte für die Token-Übereinstimmung zu
    • Sortieren Sie die Eintrags-IDs nach Punkten
    • Wenn die Punktwerte gleich sind, verwenden Sie das Datum, um die Ergebnisse zu sortieren

Was ich tun möchte, aber nicht herausgefunden habe, ist, eine Abfrage zu senden, die so etwas wie die Ergebnisse von in() zurückgibt, aber eine doppelte Eintrags-ID für jedes Token zurückgibt, das mit jeder überprüften Eintrags-ID übereinstimmt.

Gibt es eine bessere Möglichkeit, dies zu tun, als das, was ich tue, indem ich mehrere einzelne Abfragen verwende, die eine Abfrage pro Token ausführen?Wenn ja, wie lassen sich diese am einfachsten umsetzen?

bearbeiten
Ich habe die Einträge bereits tokenisiert, sodass beispielsweise „see spot run“ die Eintrags-ID 1 und die drei Token „see“, „spot“ und „run“ hat. Diese befinden sich in einer separaten Token-Tabelle. mit für sie relevanten Eintrags-IDs, sodass die Tabelle etwa so aussehen könnte:

'see', 1 
'spot', 1 
'run', 1 
'run', 2 
'spot', 3 
War es hilfreich?

Lösung

Sie könnten dies in einer Abfrage mit „UNION ALL“ in MySQL erreichen.

Durchlaufen Sie einfach die Tokens in PHP und erstellen Sie für jedes Token eine UNION ALL:

Wenn die Token beispielsweise „x“, „y“ und „z“ sind, könnte Ihre Abfrage etwa so aussehen

SELECT * FROM `entries` 
WHERE token like "%x%" union all 
    SELECT * FROM `entries` 
    WHERE token like "%y%" union all 
        SELECT * FROM `entries` 
        WHERE token like "%z%" ORDER BY score ect...

Die Order-Klausel sollte auf die gesamte Ergebnismenge als Ganzes angewendet werden, was Sie benötigen.

In Bezug auf die Leistung wird es nicht so schnell sein (vermute ich), aber bei Datenbanken besteht der größte Mehraufwand in Bezug auf die Geschwindigkeit oft darin, die Abfrage von PHP an die Datenbank-Engine zu senden und die Ergebnisse zu empfangen.Bei dieser Technik geschieht dies nur einmal statt einmal pro Token, sodass die Leistung steigt. Ich weiß nur nicht, ob das ausreicht.

Andere Tipps

Ich weiß, dass dies nicht unbedingt eine Antwort auf die Frage ist, die Sie stellen aber wenn Ihre Tabelle Tausende statt Millionen Zeilen umfasst, dann könnte eine VOLLTEXT-Lösung hier der beste Weg sein.

Wenn Sie in MySQL MATCH für Ihre indizierte Spalte verwenden, erhält jedes von Ihnen angegebene Schlüsselwort einen Relevanzwert (ungefähr berechnet anhand der Häufigkeit, mit der jedes Schlüsselwort erwähnt wurde), der genauer als Ihre Methode und bei mehreren Schlüsselwörtern sicherlich effizienter ist.

Siehe hier:http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html

Wenn Sie das UNION ALL-Muster verwenden, möchten Sie möglicherweise auch die folgenden Teile in Ihre Abfrage einschließen:

SELECT COUNT(*) AS C
...
GROUP BY ID
ORDER BY c DESC

Obwohl dies ein wirklich triviales Beispiel ist, erhalten Sie dennoch die Häufigkeit der Übereinstimmungen für jedes Ergebnis, und dies könnte zunächst einmal ein Pseudo-Rang sein.

Sie werden wahrscheinlich eine wesentlich bessere Leistung erzielen, wenn Sie statt einer Datenbank eine für Suchaufgaben konzipierte Datenstruktur verwenden.Sie könnten beispielsweise versuchen, einen Blick auf den Bau eines zu werfen invertierter Index.Anstatt es jedoch selbst zu schreiben, möchten Sie sich vielleicht auch mit so etwas befassen Lucene das Ihnen die meiste Arbeit abnimmt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top