2008-09-06 7 views
9

Ich habe ein Webapp-Entwicklungsproblem, für das ich eine Lösung entwickelt habe, aber ich versuche, andere Ideen zu finden, die einige Leistungsprobleme umgehen können, die ich sehe.How-to: Ranking Suchergebnisse

Problemstellung:

  • ein Benutzer gibt mehrere Schlüsselwörter/Token
  • die Anwendung sucht nach Übereinstimmungen mit den Tokens
  • für jedes Token ein Ergebnis benötigen
    • dh wenn ein Eintrag hat 3 tokens, ich brauche die entry id 3 mal
  • ran k die Ergebnisse
    • assign X Punkte für Token Spiel
    • Art der Eintrag-IDs basierend auf Punkte
    • wenn Punktwerte gleich sind, verwenden Datum sortieren Ergebnisse

Was ich wollen, aber nicht herausgefunden haben, ist es, eine Abfrage zu senden, die etwas zurückgibt, das den Ergebnissen eines in() ähnlich ist, aber eine doppelte Eintrags-ID für jedes Token liefert, das für jede überprüfte Eintrags-ID übereinstimmt.

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

bearbeiten
Ich habe bereits die Einträge in Token aufgeteilt, so zum Beispiel "Spot laufen sehen" hat einen Eintrag-ID von 1, und drei Token, 'sehen', 'vor Ort', 'Ausführen', und die sind in einem separaten Token-Tabelle, mit Eintrag für sie relevanten ids so die Tabelle wie folgt aussehen könnte:

'see', 1 
'spot', 1 
'run', 1 
'run', 2 
'spot', 3 

Antwort

6

Sie dies in einer Abfrage achive könnte ‚UNION ALL‘ in MySQL.

Gerade Schleife durch die Tokens in PHP eine UNION ALL für jedes Token zu erstellen:

zB wenn die Tokens 'x' sind, 'y' und 'z' Ihre Abfrage so etwas wie dieses

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... 
aussehen

Die Order-Klausel sollte auf die gesamte Ergebnismenge als eine funktionieren, was Sie brauchen.

In Bezug auf die Leistung wird es nicht so schnell sein (ich denke), aber mit Datenbanken der Hauptaufwand in Bezug auf die Geschwindigkeit ist oft die Abfrage der Datenbank-Engine von PHP und Empfangen der Ergebnisse. Bei dieser Technik passiert das nur einmal statt einmal pro Token, so dass die Leistung steigt, ich weiß einfach nicht, ob es reichen wird.

+0

@rmbarnes - dies sein muss, wo diese UNION ops sah ich in db Grundlagen Jahren plötzlich Sinn machen; Ich gebe definitv einen Leistungslauf, um zu sehen, wie es in der Gesamtgeschwindigkeit vergleicht – warren

+0

Denken Sie daran, UNION ALL nicht nur UNION zu verwenden, sonst denke ich nicht, dass Sie mehrere Zeilen mit der gleichen ID wie gewünscht erhalten werden. - Rambarnes 6. September 08 um 20:23 Uhr – warren

1

Wenn Sie sich mit der UNION ALL Muster, das Sie auch folgende Teile auf Ihre Anfrage Möchten Sie folgendes umfassen:

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

Zwar ist dies ein wirklich einfaches Beispiel ist es die Frequenz der Spiele bekommt für jedes Ergebnis und dies könnte ein Pseudo-Rang sein, um damit zu beginnen.

0

Sie erhalten wahrscheinlich eine viel bessere Leistung, wenn Sie eine Datenstruktur verwenden, die eher für Suchaufgaben als für eine Datenbank konzipiert ist. Beispielsweise könnten Sie versuchen, eine inverted index zu erstellen. Anstatt sich selbst zu schreiben, möchten Sie vielleicht auch in etwas wie Lucene schauen, das die meiste Arbeit für Sie erledigt.

3

Ich weiß, das ist nicht unbedingt eine Antwort auf die Frage, die Sie stellen aber wenn Ihre Tabelle Tausende statt Millionen von Zeilen ist, dann eine FULLTEXT-Lösung könnte der beste Weg, um hier zu gehen. In MySQL, wenn Sie MATCH für Ihre indizierte Spalte verwenden, wird jedes von Ihnen angegebene Keyword mit einem Relevanzwert versehen (der ungefähr nach der Anzahl der Stichwörter berechnet wird), der genauer als Ihre Methode und sicherlich effizienter ist für mehrere Keywords.

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