2012-01-09 163 views
0

我有2個Django模型:合併多個Django的結果集

class Foo(models.Model): 
    baz = models.CharField() 

class Bar(models.Model); 
    foo = models.ForeignKey(Foo) 
    qux = models.CharField() 

數據如下:

Foo 
id baz 
4 X 
5 Y 
6 Z 

Bar 
id foo_id qux 
1 4  A 
2 5  A 
3 5  B 
4 6  B 

現在我做2個查詢上酒吧,過濾上qux:

resA = [1, 2] (actually bar instances; shown bar.id for convenience) 
resB = [3, 4] (actually bar instances; shown bar.id for convenience) 

什麼是現在最快的方式與這些列表在一起,以便結果將是:

resAND = [5] (foo.id) 

現在我做:

ret = [] 
nr_sets = 2 
foos = Foo.objects.all() 
bars = list(resA + resB) 
for foo in foos: 
    test = filter(lambda bar : bar.foo_id == foo.id, bars) 
    if test == nr_sets; 
     ret.append(foo) 

然而,這是可怕的慢。任何想法在加速?我特別尋找後期查詢解決方案,但也歡迎關於查詢('s)的好主意。

+0

「什麼是現在最快的方式與這些列表結合在一起,以便結果如下:」?你能解釋這個結果是如何來自這兩個列表的? 「AND」一詞似乎並不適用。 – 2012-01-09 11:44:15

+0

只是做一個新的查詢而不是試圖結合兩個查詢不是更簡單(也更快)嗎? – 2012-01-09 11:47:15

回答

1

你可以嘗試

foo_ids = set(resA.values_list('foo_id', flat=True)) & \ 
    set(resB.values_list('foo_id', flat=True)) 

然後你就可以得到相應的完整Foo對象與

ret = Foo.objects.in_bulk(foo_ids).values() 

編輯:使用set因爲很顯然&ValueQuerySet不能按預期工作。

+0

不錯的方法,但我沒有&操作符在ValuesQuerySet之間工作。在這個問題中改變了一個元組交集的那個; http://stackoverflow.com/questions/642763/python-intersection-of-two-lists – RickyA 2012-01-09 13:22:48

+0

好的,謝謝 - 老實說,我沒有嘗試過。更新我的答案以使用'set's。 – 2012-01-09 13:27:13

+0

你不能'&'設置。我使用了:b1 = [1,2,3,4,5] b2 = [3,4,5,6] s2 = set(b2) b3 = [val在b1中的val,如果在s2中val] ' – RickyA 2012-01-09 13:31:22

0

爲什麼不:

Bar.objects.filter(foo__id=5) 

您也可以在裏面添加其他濾波器參數,它們將被默認AND運算。

+0

,因爲我不知道它會是5. 5是答案,而不是輸入。 – RickyA 2012-01-09 12:33:32