2012-06-09 1 views
7

Ich arbeite an einem Projekt (in Django geschrieben), das nur wenige Entitäten, aber viele Zeilen für jede Entität hat.Erstellen einer DSL-Abfragesprache

In meiner Anwendung habe ich mehrere statische "Berichte", direkt in SQL geschrieben. Die Benutzer können die Datenbank auch über ein generisches Filterformular durchsuchen. Da die Zielgruppe wirklich technisch versiert ist und der Filter zu einem bestimmten Zeitpunkt nicht ihren Bedürfnissen entspricht, denke ich über das Erstellen einer Abfragesprache für meine Datenbank wie YQL oder Jira's advanced search nach.

Ich fand http://sourceforge.net/projects/littletable/ und http://www.quicksort.co.uk/DeeDoc.html, aber es scheint, dass sie nur auf In-Memory-Objekte arbeiten. Da die Datenbank zu groß sein kann, um sie im Speicher zu halten, würde ich bevorzugen, dass die Abfrage in SQL (oder besser eine Django-Abfrage) übersetzt wird, bevor die eigentliche Arbeit ausgeführt wird.

Gibt es eine Bibliothek oder Best Practices, um dies zu tun?

+0

Sie könnten dieses Zope Add-on als Beispiel ansehen: http://www.dieter.handshake.de/pyprojects/zope/AdvancedQuery.html –

+0

Aber SQL ist schon DSL) – Denis

Antwort

2

Ich habe genau dieses Problem konfrontiert - eine große Datenbank, die Suche benötigt. Ich habe einige statische Berichte und mehrere ausgefallene Filter mit django (sehr einfach mit Django) gemacht, genau wie du.

Aber die Power-User forderten mehr. Ich entschied, dass es bereits eine DSL gab, die sie alle kannten - SQL. Die Frage war, wie man es sicher genug machen kann.

Also habe ich Django-Berechtigungen verwendet, um den Power-Usern die Berechtigung zu geben, SQL-Abfragen in einer neuen Tabelle durchzuführen. Ich machte dann eine Ansicht für die nicht ganz so mächtigen Benutzer, diese Abfragen zu verwenden. Ich ließ sie optionale Parameter nehmen. Die Abfragen wurden mit der unteren Ebene DB-API von Python ausgeführt, die Django sowieso für sein ORM unter der Haube verwendet.

Der eigentliche Trick war das Öffnen einer schreibgeschützten Datenbankverbindung, um diese Abfragen auszuführen, nur um sicherzustellen, dass keine Updates jemals ausgeführt wurden. Ich habe eine schreibgeschützte Verbindung hergestellt, indem ich einen anderen Benutzer in der Datenbank mit niedrigeren Berechtigungen erstellt und eine bestimmte Verbindung in der Ansicht geöffnet habe.

TL, DR - SQL ist der Weg zu gehen!

+0

Ich dachte schon daran, die Möglichkeit für rohe hinzuzufügen SQL-Abfragen, aber ich bin nicht sehr glücklich damit. SQL-Abfragen auf eine schnelle und intelligente Weise durchzuführen ist manchmal wirklich schwierig. So könnte ich (und Sie) am Ende Abfragen ausführen, die die Datenbank stark belasten. Und Sie müssen sicherstellen, dass die SQL-Schnittstelle es nicht erlaubt, Daten aus anderen Tabellen auszuwählen, oder Sie haben eine Sicherheitslücke in Bezug auf die Offenlegung von Informationen (-> komplexer zu verwalten). Allerdings kann selbst technisch versierter Anwender SQL nicht kennen (oder nicht wissen). – ercpe

1

Abhängig von der Art Ihrer Daten, den Arten von Abfragen, die Ihre Benutzer verwenden müssen, und der Häufigkeit, mit der Ihre Daten aktualisiert werden, ist eine Alternative zu der von Nick Craig-Wood vorgeschlagenen reinen SQL-Lösung die Indizierung Ihrer Daten Solr und dann Abfragen ausführen.

Solr ist eine zusätzliche Ebene der Komplexität (Konfiguration, Datensynchronisation), aber es ist super-schnell, kann mit großen Datenmengen umgehen und bietet eine (relativ) intuitive Abfragesprache.

+0

Ich denke, dass ein ausgewachsener Suchrahmen (wegen der erwähnten Komplexität) ein großer Overkill ist. Die Daten werden regelmäßig aktualisiert, so dass viel Code/Logik benötigt wird, um die Datenspeicher synchron zu halten. – ercpe

1

Sie könnten Ihre eigene SQL-ish-Sprache mit pyparsing schreiben. Es gibt sogar ziemlich ausführliche example, die Sie erweitern könnten.

12

Schreiben solch ein DSL ist eigentlich überraschend einfach mit PLY, und was ho-es gibt bereits ein Beispiel für genau das, was Sie wollen, in Django. Seht ihr, Django hat dieses fantastische Ding namens Q object, was die Django-Seite recht leicht macht.

Auf DjangoCon EU 2012 gab Matthieu Amiguet eine Sitzung Implementierung domänenspezifische Sprachen in Django-Anwendungen, in dem das Recht er durch den Prozess gegangen, bis hin eine solche DSL zur Umsetzung, wie Sie wünschen. His slides, which include all you need, are available on his website. Der endgültige Code (mit der letzten Folie verknüpft) ist verfügbar unter http://www.matthieuamiguet.ch/media/misc/djangocon2012/resources/compiler.html.

Reinout van Rees produzierte auch einige good comments on that session. (Das tut er normalerweise!) Diese decken ein wenig vom fehlenden Kontext ab.

Sie dort sehen, etwas sehr ähnlich YQL und JQL in den Beispielen angegeben:

  • groups__name="XXX" AND NOT groups__name="YYY"
  • (modified > 1/4/2011 OR NOT state__name="OK") AND groups__name="XXX"

Es kann auch sehr leicht gezwickt werden; zum Beispiel möchten Sie möglicherweise groups.name statt groups__name (würde ich) verwenden. Diese Modifikation könnte ziemlich trivial gemacht werden (erlauben Sie . im FELD-Token, indem Sie t_FIELD modifizieren und dann . durch __ ersetzen, bevor Sie das Q Objekt in p_expression_ID konstruieren).

So erfüllt das einfache Abfragen; es gibt Ihnen auch einen guten Ausgangspunkt, wenn Sie ein komplexeres DSL machen möchten.

+0

Danke für Ihre Antwort. Leider ist die weitere Entwicklung dieses Projekts auf Eis gelegt worden, daher kann ich es im Moment nicht versuchen. Aber von einem schnellen Blick sieht das wie eine gute Lösung aus. Wenn die Entwicklung weitergeht, werde ich das definitiv versuchen und werde deine Antwort gerne annehmen. – ercpe

+0

Ich öffnete Kopfgeld auf diese Frage, weil ich genau das gleiche brauche. Diese Antwort scheint mir genau das zu sein, wonach ich gesucht habe. Die Folien sind sehr hilfreich. Ich werde nächste Woche in dieses Problem eintauchen und hoffentlich werde ich bald in der Lage sein, diesen Ansatz zu bestätigen und Ihnen zuzusprechen. –

+0

Genau das möchte ich auch. Dies, was zu Suchergebnissen oder Berichten führt, würde Django-Modelle noch leistungsfähiger machen. Schätze, wir wurden alle von Jira verwöhnt :) –