2010-03-12 15 views
8

Ich mache eine App, die Rückwärtssuchen benötigt. Damit meine ich, dass Benutzer der App Suchparameter eingeben und speichern; Wenn neue Objekte in das System eingegeben werden, wird eine Benachrichtigung gesendet, wenn sie mit den vorhandenen Suchparametern eines Benutzers übereinstimmen.Rückwärtssuche Best Practices?

Es fällt mir schwer, Lösungen für diese Art von Problem zu finden .

ich Django bin mit und denke an die Durchsuchungen Bau und Beizen ihnen Q Objekte mit wie hier beschrieben: http://www.djangozen.com/blog/the-power-of-q

So wie ich es sehe, wenn ein neues Objekt in die Datenbank eingegeben, ich werde laden müssen jede einzelne gespeicherte Abfrage von der Datenbank und irgendwie gegen dieses ein neues Objekt laufen lassen, um zu sehen, ob es dieser Suchanfrage entsprechen würde ... Das scheint nicht ideal - hat jemand solch ein Problem schon einmal angepackt?

Antwort

4

Auf Datenbankebene bieten viele Datenbanken "Trigger" an.

Ein anderer Ansatz besteht darin, zeitgesteuerte Jobs zu verwenden, die regelmäßig alle Elemente aus der Datenbank abrufen, die seit der letzten Ausführung ein Datum der letzten Änderung aufweisen. dann werden diese gefiltert und Warnungen ausgegeben. Sie können möglicherweise einen Teil der Filterung in die Abfrageanweisung in der Datenbank einfügen. Dies ist jedoch ein wenig komplizierter, wenn Benachrichtigungen gesendet werden müssen, wenn Elemente gelöscht werden.

Sie können Trigger auch manuell in den Code einfügen, der Daten an die Datenbank sendet, die möglicherweise flexibler ist und sicherlich nicht auf bestimmten Funktionen der Datenbank beruht.

Eine nette Möglichkeit für die Kommunikation zwischen Triggern und Alarmen besteht in Nachrichtenwarteschlangen - Warteschlangen wie RabbitMQ und andere AMQP Implementierungen werden mit Ihrer Site skaliert.

4

Der Aufwand, den Sie verwenden, um dieses Problem zu lösen, steht in direktem Zusammenhang mit der Anzahl der gespeicherten Abfragen, mit denen Sie zu tun haben.

Vor über 20 Jahren behandelt wir gespeicherten Abfragen von ihnen als minidocs Behandlung und ihnen die Indizierung auf der Basis aller der haben muss und Begriffe haben kann. Die Termliste eines neuen Dokuments wurde als eine Art Abfrage für diese "Datenbank von Abfragen" verwendet und erstellte eine Liste von möglichen interessanten Suchvorgängen, die ausgeführt werden mussten, und dann wurden nur diese Suchanfragen mit den neuen Dokumenten ausgeführt. Das mag verschlungen klingen, aber wenn es mehr als ein paar gespeicherte Abfragen gibt (sagen Sie irgendwo von 10.000 bis 1.000.000 oder mehr) und Sie haben eine komplexe Abfragesprache, die eine Mischung aus booleschen und ähnlichkeitsbasierten Suchen unterstützt, reduziert es erheblich Nummer mussten wir als Full-On-Abfragen ausführen - oft nicht mehr als 10 oder 15 Abfragen.

Eine Sache, die geholfen hat, war, dass wir die Kontrolle über die horizontal and the vertical der ganzen Sache hatten. Wir haben unseren Abfrageparser verwendet, um einen Parserbaum zu erstellen, und dieser wurde verwendet, um die Liste der Muss-/Kann-Begriffe zu erstellen, unter denen wir die Abfrage indiziert haben. Wir haben den Kunden davor gewarnt, bestimmte Arten von Platzhaltern in den gespeicherten Abfragen zu verwenden, da dies zu einer Explosion der Anzahl der ausgewählten Abfragen führen könnte.

Update für Kommentar:

Kurze Antwort: Ich weiß es nicht sicher.

Längere Antwort: Wir hatten es mit einer benutzerdefinierten Textsuchmaschine zu tun, und ein Teil der Abfragesyntax erlaubte es, die Doc-Sammlung auf sehr effiziente Weise zu schneiden, mit besonderem Schwerpunkt auf date_added. Wir haben viele Spiele gespielt, weil wir pro Tag 4-10.000.000 neue Dokumente eingesammelt haben und diese gegen bis zu 1.000.000 gespeicherte Abfragen auf einem DEC Alphas mit 64 MB Hauptspeicher ausgeführt haben. (Das war in den späten 80er/frühen 90er Jahre.)

Ich vermute, dass etwas auf Filterung entspricht date_added in Kombination verwendet getan werden könnte, das Datum der letzten Mal, wenn Sie Ihre Fragen lief, oder vielleicht die höchste id an letzte Abfrage Laufzeit. Wenn Sie die Abfragen für einen geänderten Datensatz erneut ausführen müssen, können Sie dessen id als Teil der Abfrage verwenden.

Um genauer zu werden, müssen Sie ein Los spezifischer über genau welches Problem Sie versuchen zu lösen und die Skala der Lösung, die Sie versuchen zu erreichen.

+0

Ihr Konzept von "muss haben" und "haben Sie vielleicht" Suchbegriffe ist sehr sinnvoll in der Verringerung der Anzahl der gespeicherten Suchen, die gegen neue Dokumente ausgeführt werden müssen. Der zweite Teil der Frage ist mehr django bezogen - sagen Sie haben eine Modellinstanz - wie genau würde man einen Filter/eine Abfrage gegen nur diese eine Instanz ausführen, um eine boolesche Übereinstimmung zu bestimmen? – edub

+0

+1, habe ich über Lösungen für dieses Problem nachgedacht und kam zu der gleichen Lösung. Obwohl ich immer noch nach anderen möglichen Lösungen suche, ist dieses Design viel besser, als jede gespeicherte Abfrage zu durchlaufen, um zu prüfen, ob sie mit einem neuen Eintrag übereinstimmt. Danke fürs Schreiben. –

1

Wenn Sie den/die Objekttyp (en) für jede gespeicherte Suche als generic relation gespeichert haben, können Sie allen beteiligten Objekten einen Post-Save-Eintrag signal hinzufügen. Wenn das Signal ausgelöst wird, sucht es nur nach den Suchvorgängen, die den Objekttyp betreffen, und führt diese aus. Das wird wahrscheinlich immer noch zu Skalierungsproblemen führen, wenn Sie eine Menge Schreibvorgänge in der Datenbank und viele gespeicherte Suchen haben, aber es wäre ein einfacher Django-Ansatz.

+0

Wenn Sie darüber nachdenken, wenn Sie es als Cron-Aufgabe gemacht haben oder Sellerie/Ähnliches verwendet haben, um neue Elemente außerhalb des Speicherprozesses zu verarbeiten, müssen Sie sich keine Sorgen über die Skalierung machen. – Tom