2012-01-09 137 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