這將是一個「漫長的」。我儘可能地包含儘可能多的代碼和解釋......如果有必要,我不會拋出代碼。在django-query中實現邏輯分析器
我想在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。我用一個瘋狂的字符串-EVAL黑客創建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分鐘才能完成所有樣本。所以我每晚計算籃子,然後在白天凍結它們。我擔心,隨着我開始策劃更多的籃子,樣品和標籤會變得很糟糕。
有什麼建議嗎?
我也嘗試過將「()」類型的查詢分解爲更長的,但沒有parens的等價版本,但還沒有能夠使這些工作。 – JudoWill 2010-01-05 05:05:46