2012-06-09 6 views
7

estoy trabajando en un proyecto (escrito en Django) que tiene solo unas pocas entidades, pero muchas filas para cada entidad.Creando un lenguaje de consulta DSL

En mi aplicación tengo varios "informes" estáticos, escritos directamente en SQL simple. Los usuarios también pueden buscar en la base de datos a través de un formulario de filtro genérico. Dado que el público objetivo es realmente conocedor de la tecnología y en algún momento el filtro no se ajusta a sus necesidades, pienso en crear un lenguaje de consulta para mi base de datos como YQL o Jira's advanced search.

Encontré http://sourceforge.net/projects/littletable/ y http://www.quicksort.co.uk/DeeDoc.html, pero parece que solo funcionan en objetos en memoria. Como la base de datos puede ser demasiado grande para almacenarla en la memoria, preferiría que la consulta se traduzca en SQL (o mejor en una consulta de Django) antes de realizar el trabajo real.

¿Hay alguna biblioteca o mejores prácticas sobre cómo hacer esto?

+0

Puede ver este complemento de Zope como ejemplo: http://www.dieter.handshake.de/pyprojects/zope/AdvancedQuery.html –

+0

Pero SQL ya es DSL) – Denis

Respuesta

2

Me he enfrentado exactamente a este problema: una gran base de datos que necesita buscar. Hice algunos informes estáticos y varios filtros sofisticados utilizando django (muy fácil con django) como usted.

Sin embargo, los usuarios avanzados reclamaban más. Decidí que ya había un DSL que todos sabían: SQL. La pregunta era cómo hacerlo lo suficientemente seguro.

Así que utilicé los permisos django para dar permiso a los usuarios avanzados para realizar consultas SQL en una nueva tabla. Luego hice una vista para que los usuarios no tan poderosos usen estas consultas. Los hice tomar los parámetros opcionales. Las consultas se ejecutaron usando el nivel inferior de Python DB-API que django usa de todos modos para su ORM.

El verdadero truco fue abrir una conexión de base de datos de solo lectura para ejecutar estas consultas solo para asegurarse de que no se ejecutaran actualizaciones. Hice una conexión de solo lectura creando un usuario diferente en la base de datos con permisos más bajos y abriendo una conexión específica para eso en la vista.

TL; DR - SQL es el camino a seguir!

+0

Ya pensé en agregar la posibilidad de usar raw Consultas SQL, pero no estoy muy contento con esto. Hacer consultas SQL de manera rápida e inteligente a veces es realmente complicado. Así que yo (y usted) podríamos terminar ejecutando consultas que colocan mucha carga en la base de datos. Y debe asegurarse de que la interfaz sql no le permita seleccionar datos de otras tablas o que termine con una vulnerabilidad de divulgación de información (-> más compleja de administrar). Sin embargo, incluso los conocedores de la tecnología pueden no saber (o no quieren saber) SQL. – ercpe

1

Dependiendo de la forma de sus datos, los tipos de consultas que sus usuarios necesitan usar y la frecuencia con la que se actualizan sus datos, una alternativa a la solución SQL pura sugerida por Nick Craig-Wood es indexar sus datos en Solr y luego ejecutar consultas en su contra.

Solr es una capa adicional de complejidad (configuración, sincronización de datos) pero es superrápida, puede manejar grandes conjuntos de datos y proporciona un lenguaje de consulta (relativamente) intuitivo.

+0

Creo que un marco de búsqueda completo es una gran exageración (debido a la complejidad mencionada). Los datos se actualizan de manera regular, por lo que requeriría una gran cantidad de código/lógica para mantener sincronizados los almacenes de datos. – ercpe

1

Puede escribir su propio lenguaje SQL-ish usando pyparsing, en realidad. Incluso hay bastante detallado example que podría extender.

12

Escribir una DSL de este tipo es sorprendentemente fácil con PLY, y hay un ejemplo disponible para hacer exactamente lo que se desea en Django. Verás, Django tiene esta cosa elegante llamada Q object que hace que el lado de Django sea bastante fácil.

En DjangoCon UE 2012, Matthieu Amiguet dio una sesión titulada Idiomas Ejecución de dominio específicos en aplicaciones Django en la que pasó por el proceso, hasta la implementación de un DSL tales como desee. His slides, which include all you need, are available on his website. El código final (vinculado a partir de la última diapositiva, de todos modos) está disponible en http://www.matthieuamiguet.ch/media/misc/djangocon2012/resources/compiler.html.

Reinout van Rees también produjo algunos good comments on that session. (¡Normalmente lo hace!) Estos cubren un poco del contexto faltante.

Ves allí algo muy similar a YQL y JQL en los ejemplos dados:

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

También puede ser ajustado muy fácilmente; por ejemplo, es posible que desee utilizar groups.name en lugar de groups__name (lo haría). Esta modificación podría hacerse de manera bastante trivial (permita . en el token FIELD, modificando t_FIELD, y luego reemplazando . con __ antes de construir el objeto Q en p_expression_ID).

Por lo tanto, eso satisface la consulta simple; también te ofrece un buen punto de partida si deseas crear una DSL más compleja.

+0

Gracias por su respuesta. Lamentablemente, el desarrollo adicional de este proyecto se ha suspendido, por lo que no puedo probarlo en este momento. Sin embargo, de un vistazo rápido, parece una buena solución. Si el desarrollo continúa, definitivamente intentaré esto y aceptaré felizmente tu respuesta. – ercpe

+0

Abrí recompensa en esta pregunta, porque necesito exactamente lo mismo. Esta respuesta parece ser brillante para mí, precisamente lo que he estado buscando. Las diapositivas son muy útiles. Voy a bucear en este problema la próxima semana y espero poder validar pronto este enfoque y premiarte. –

+0

Esto es exactamente lo que me gustaría también. Esto, que lleva a resultados de búsqueda o informes, haría que los modelos Django sean aún más poderosos. Supongo que todos hemos sido mimados por Jira :) –