django - 在 django-query 中实现逻辑解析器

标签 django django-queryset logical-operators

这将是一个“长篇”。我包含尽可能多的代码和解释......如果有必要,我不会放弃代码。

我正在尝试在 django 查询系统中实现逻辑解析器。用户可以在其中针对应用于样本的标签提供复杂的查询。这本质上是科学样本库的一部分,用户可以在其中应用定义的标签(组织类型、研究的疾病等)。然后,他们可以创建由对这些标签的逻辑查询定义的样本的持久“篮子”。

#models.py

class Sample(models.Model):
    name = models.CharField(max_length = 255)


class Tag(models.Model):
    name = models.CharField(max_length = 255)
    samples = models.ManyToManyField(Sample)

A quick example:
#example data:
Sample1 has TagA, TagB, TagC
Sample2 has       TagB, TagC, TagD
Sample3 has TagA,       TagC, TagD
Sample4 has       TagB

#example query:
'TagB AND TagC AND NOT TagD'

将返回 Sample1。我使用了一个疯狂的 string-eval hack 来创建一组 Q()对象:
def MakeQObject(expression):
    """
    Takes an expression and uses a crazy string-eval hack to make the qobjects.
    """
    log_set = {'AND':'&','OR':'|','NOT':'~'}

    exp_f = []
    parts = expression.split()
    #if there is a ) or ( then we can't use this shortcut
    if '(' in parts or ')' in parts:
        return None

    for exp in parts:
        if exp in log_set:
            exp_f.append(log_set[exp])
        else:
            exp_f.append("Q(tags__name__iexact = '%s')" % exp)
    st = ' '.join(exp_f)
    qobj = eval(st)
    return qobj

但是,这在任何需要复杂的操作顺序或按 () 分组的情况下都会失败。给定相同的示例数据,查询:(TagA OR TagB) AND NOT TagD应该返回 Sample1、Sample4 但不返回。我已经实现了一个“一次一个”函数,它可以获取一个 Sample 对象并执行查询。然而,在我的实际数据库中,我有约 40,000 个样本和约 400 个标签(每个样本约 7 个),迭代技术需要约 4 分钟才能完成所有样本。所以我每晚计算篮子,然后在白天把它们冷冻起来。我担心当我开始策划更多的篮子、样本和标签时,这将无法扩展。

有什么建议么?

最佳答案

首先,为了提高性能,在标签名称字段上添加索引可能会有所帮助,因为您正在使用它进行查询。所以,添加 db_index=真到你的专栏:

class Tag(models.Model):
    name = models.CharField(max_length = 255, db_index=True)
    samples = models.ManyToManyField(Sample)

其次,为了解析用户查询,我建议使用几个好的基于 Python 的解析器之一,例如 PyParsing。或 PLY .这些乍一看可能令人生畏,但实际上并不难,尤其是像您这样的简单语法。

如果这些对您来说太多了,那么请尝试使用 Fredrik 的指南 Simple Top-Down Parsing in Python 自己动手。 .

关于django - 在 django-query 中实现逻辑解析器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2004190/

相关文章:

python - 媒体文件上的 404 - Django

python - 通过多对多枚举相关对象

python - 模板标签返回 None

python - 如何设置 ndb keyProperty

python - 按子类类型过滤

javascript - 对于奇数测试,按位 AND 运算符总是比模数快(仍然)吗?

Django 查询集过滤器空 JSONField

django ModelMultipleChoiceField 查询集/过滤器已关联的对象

java - 我该怎么做才能让程序输出 1 和 0 而不是 true 和 false?

python - 为什么此 Python 语句中的 'and/or' 操作行为异常?