构建DSL查询语言

时间:2012-06-09 08:21:13

标签: python django dsl

我正在开发一个项目(用Django编写),它只有几个实体,但每个实体都有很多行。

在我的应用程序中,我有几个静态“报告”,直接用纯SQL编写。用户还可以通过通用过滤器表单搜索数据库。由于目标受众真的精通技术,并且在某些时候过滤器不符合他们的需求,我考虑为我的数据库创建查询语言,如YQLJira's advanced search

我找到了http://sourceforge.net/projects/littletable/http://www.quicksort.co.uk/DeeDoc.html,但似乎它们只对内存中的对象进行操作。由于数据库可能太大而无法将其保存在内存中,我宁愿在执行实际工作之前将查询转换为SQL(或更好的Django查询)。

是否有关于如何执行此操作的库或最佳实践?

4 个答案:

答案 0 :(得分:14)

使用PLY编写这样的DSL实际上非常容易,并且在Django中已经有一个可用于实现您想要的示例。你知道,Django有一个名为Q object这个奇特的东西,它使得Django查询事物相当容易。

在DjangoCon EU 2012上,Matthieu Amiguet举办了一个名为在Django应用程序中实现特定领域语言的会议,在这个会议中,他完成了整个过程,直到根据需要实现这样的DSL。 His slides, which include all you need, are available on his website. http://www.matthieuamiguet.ch/media/misc/djangocon2012/resources/compiler.html提供了最终代码(最后一张幻灯片链接){/ 3}}。

Reinout van Rees也制作了一些good comments on that session。 (他通常会这样做!)这些内容涵盖了一些缺失的背景。

在给出的示例中,您会看到与YQL和JQL非常相似的内容:

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

它也可以很容易地调整;例如,您可能希望使用groups.name而不是groups__name(我愿意)。通过修改.,然后在构造t_FIELD对象之前将.替换为__,可以相当简单地进行此修改(允许{1}}在FIELD令牌中在Q)。

因此,这满足简单的查询;如果您希望制作更复杂的DSL,它还为您提供了良好的起点。

答案 1 :(得分:3)

我遇到了这个问题 - 一个需要搜索的大型数据库。我使用django(非常容易使用django)制作了一些静态报告和几个花哨的过滤器,就像你一样。

然而,高级用户吵着要求更多。我决定已经有一个DSL他们都知道了 - SQL。问题是如何使其足够安全。

因此,我使用django权限为超级用户授予在新表中进行SQL查询的权限。然后,我找到了那些不那么强大的用户使用这些查询的视图。我让他们采取可选参数。查询是使用Python的低级DB-API运行的,django无论如何都在使用它的ORM。

真正的诀窍是打开一个只读数据库连接来运行这些查询,以确保没有运行任何更新。我通过在数据库中创建具有较低权限的不同用户并在视图中为其打开特定连接来建立只读连接。

TL; DR - SQL是要走的路!

答案 2 :(得分:1)

根据数据的形式,用户需要使用的查询类型以及数据更新的频率,Nick Craig-Wood建议的纯SQL解决方案的替代方法是将数据编入索引{ {3}}然后对它运行查询。

Solr是一个复杂的附加层(配置,数据同步),但它超快,可以处理大型数据集,并提供(相对)直观的查询语言。

答案 3 :(得分:1)

实际上,您可以使用pyparsing编写自己的SQL-ish语言。你可以扩展甚至是非常冗长的example