2012-06-09 14 views
7

Sto lavorando a un progetto (scritto in Django) che ha solo poche entità, ma molte righe per ogni entità.Creazione di una lingua di query DSL

Nella mia applicazione ho diversi "report" statici, scritti direttamente in SQL semplice. Gli utenti possono anche cercare nel database tramite un modulo di filtro generico. Dal momento che il pubblico di destinazione è davvero esperto di tecnologia e ad un certo punto il filtro non si adatta alle loro esigenze, penso a creare un linguaggio di query per il mio database come YQL o Jira's advanced search.

Ho trovato http://sourceforge.net/projects/littletable/ e http://www.quicksort.co.uk/DeeDoc.html, ma sembra che funzionino solo su oggetti in memoria. Poiché il database può essere troppo grande per tenerlo in memoria, preferirei che la query sia tradotta in SQL (o meglio una query di Django) prima di eseguire il lavoro effettivo.

Esistono librerie o best practice su come eseguire questa operazione?

+0

Si potrebbe guardare questo add-on di Zope come exmaple: http://www.dieter.handshake.de/pyprojects/zope/AdvancedQuery.html –

+0

Ma SQL è già DSL) – Denis

risposta

2

Ho affrontato esattamente questo problema: un database di grandi dimensioni che richiede una ricerca. Ho fatto alcuni report statici e diversi filtri di fantasia usando django (molto facile con django) proprio come hai fatto tu.

Tuttavia, gli utenti esperti chiedevano di più. Ho deciso che esisteva già uno DSL che tutti conoscevano - SQL. La domanda era come renderlo abbastanza sicuro.

Quindi ho usato i permessi django per dare ai potenti utenti il ​​permesso di creare query SQL in una nuova tabella. Poi ho fatto una vista per gli utenti non proprio così potenti da usare queste domande. Li ho fatti prendere i parametri facoltativi. Le query sono state eseguite utilizzando il livello inferiore di Python DB-API che django utilizza comunque sotto il cofano per il suo ORM.

Il vero trucco stava aprendo una connessione di database di sola lettura per eseguire queste query solo per assicurarsi che nessun aggiornamento fosse mai stato eseguito. Ho effettuato una connessione di sola lettura creando un utente diverso nel database con autorizzazioni inferiori e aprendo una connessione specifica per tale nella vista.

TL; DR - SQL è la strada da percorrere!

+0

Ho già pensato di aggiungere la possibilità per raw Query SQL, ma non sono molto contento di questo. Effettuare query SQL in modo rapido e intelligente a volte è davvero complicato. Quindi io (e tu) potremmo finire per eseguire query che mettono un sacco di carico sul database. E devi assicurarti che l'interfaccia sql non ti permetta di selezionare i dati da altre tabelle o finisci con una vulnerabilità di divulgazione delle informazioni (-> più complessa da amministrare). Tuttavia, anche i tecnici esperti potrebbero non sapere (o non voler sapere) SQL. – ercpe

1

A seconda del tipo di dati, dei tipi di query che gli utenti devono utilizzare e della frequenza di aggiornamento dei dati, un'alternativa alla soluzione SQL pura suggerita da Nick Craig-Wood consiste nell'indicizzare i dati in Solr e quindi eseguire query su di esso.

Solr è un ulteriore livello di complessità (configurazione, sincronizzazione dei dati) ma è super veloce, può gestire dataset di grandi dimensioni e fornisce un linguaggio di query (relativamente) intuitivo.

+0

Penso che un quadro di ricerca in piena regola sia un grande overkill (a causa della citata complessità). I dati vengono aggiornati regolarmente, quindi è necessario molto codice/logica per mantenere in memoria i datastore. – ercpe

1

È possibile scrivere la propria lingua SQL-ish utilizzando pyparsing, in realtà. C'è anche un bel verboso example che potresti estendere.

12

Scrivere un DSL in realtà è sorprendentemente facile con PLY e cosa c'è già un esempio disponibile per fare solo quello che vuoi, in Django. Vedete, Django ha questa strana cosa chiamata Q object che rende il lato di query di Django piuttosto semplice.

A DjangoCon UE 2012, Matthieu Amiguet ha dato una sessione dal titolo Lingue Implementazione di dominio-specifici in Django Applicazioni in cui andò attraverso il processo, fino alla realizzazione di tale DSL come volete. His slides, which include all you need, are available on his website. Il codice finale (collegato dall'ultima diapositiva, comunque) è disponibile allo http://www.matthieuamiguet.ch/media/misc/djangocon2012/resources/compiler.html.

Reinout van Rees ha anche prodotto alcuni good comments on that session. (Di solito lo fa!) Questi coprono un po 'del contesto mancante.

Vedete là dentro qualcosa di molto simile a YQL e JQL negli esempi riportati:

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

Può anche essere modificato molto facilmente; ad esempio, potresti voler utilizzare groups.name anziché groups__name (Vorrei). Questa modifica potrebbe essere semplificata (consentire . nel token FIELD, modificando t_FIELD e quindi sostituire . con __ prima di costruire l'oggetto Q in p_expression_ID).

Quindi, che soddisfa l'interrogazione semplice; ti dà anche un buon punto di partenza se desideri creare un DSL più complesso.

+0

Grazie per la risposta. Sfortunatamente ulteriori sviluppi su questo progetto sono stati messi in attesa, quindi al momento non posso provarlo. Tuttavia, da un rapido sguardo questa sembra una buona soluzione. Se lo sviluppo continua, lo proverò sicuramente e accetterò felicemente la tua risposta. – ercpe

+0

Ho aperto la taglia su questa domanda, perché ho bisogno esattamente della stessa cosa. Questa risposta sembra essere brillante per me, esattamente quello che stavo cercando. Le diapositive sono molto utili. Mi tufferò in questo problema la prossima settimana e spero di essere presto in grado di convalidare questo approccio e premiarti. –

+0

Questo è esattamente quello che mi piacerebbe. Questo, portando a risultati di ricerca o rapporti, renderebbe i modelli Django ancora più potenti. Immagino che siamo stati tutti rovinati da Jira :) –

Problemi correlati