我对Django和Python比较陌生,但是我还没有完全弄明白这一点。
我本质上想要使用过滤器为大量用户查询数据库。然后我想对这部分用户进行一系列查询。所以我认为首先查询我的更大的过滤器参数是最有效的,然后在该集合上进行单独的过滤查询。在代码中,它看起来像这样
#Get the big groups of users, like all people with brown hair.
group_of_users = Data.objects.filter(......)
#Now get all the people with brown hair and blue eyes, and then all with green eyes, etc.
for each haircolor :
subset_of_group = group_of_users.filter(....)
顺便说一下,这只是伪代码,我不是那么无能为力。我认为这会更有效,但似乎如果消除第一个查询并且只是在for循环中获取查询集,它就会快得多(实际上是时间)。 我担心这是因为当我首先过滤,然后在for循环中每次过滤时,它实际上是在每个for循环执行上进行两组过滤查询。所以真的,做我想要的工作量的两倍。我认为通过缓存这无关紧要,因为第一个过滤器结果将被缓存并且它仍然会更快,但同样,我用多次测试计时并且单个过滤器更快。有什么想法吗?
编辑: 因此,似乎无法查询一组数据,然后尝试仅针对该组数据进一步查询。相反,我应该查询一组数据,然后使用常规Python进一步解析该数据。
答案 0 :(得分:3)
正如garnertb ans lanzz所说,使用filter
函数的地方并不重要,唯一重要的是评估查询时(参见when querysets are evaluated)。我的猜测是,在您的测试中,您在代码中的某个位置评估查询集,并且在测试中使用单独的过滤器调用进行更多评估。
每当评估查询集时,都会缓存其结果。但是,如果在查询集上使用其他方法(例如filter
或order_by
),则此缓存不会延续。因此,您无法尝试评估较大的集合,并使用对查询集的过滤来检索较小的集合,而无需执行其他查询。
如果你只有一小部分染发剂,你就可以对每种染发剂进行查询。但是,如果您有许多查询,查询量将对性能产生严重影响。在这种情况下,最好对要使用的完整用户集进行查询,并在python中进行后续处理:
qs = Data.objects.filter(hair='brown')
objects = dict()
for obj in qs:
objects.setdefault(obj.haircolour, []).append(obj)
for (k, v) in objects.items():
print "Objects for colour '%s':" % k
for obj in v:
print "- %s" % obj
答案 1 :(得分:2)
在您实际尝试访问结果之前,过滤Django查询集不会执行任何数据库操作。过滤只会向查询集添加条件,然后在访问查询结果时用于构建最终查询。
分配group_of_users = Data.objects.filter(...)
时,不会从数据库中检索数据;您只需获得知道您想要满足特定条件的记录(您提供给Data.objects.filter
的过滤参数)的查询集,但它不会预先获取那些实际用户。之后,当您分配subset_of_group = group_of_users.filter(....)
时,您不会仅过滤前一组用户,而只会向查询集添加更多条件;此时仍未从数据库中恢复任何数据。 仅当您实际尝试访问查询集的结果时(通过迭代查询集,或通过切片或通过访问其中的单个索引),查询集将构建(通常) 单个查询,该查询仅检索满足您在查询集中累积的所有过滤条件的用户记录。它仍然需要过滤整个用户表以找到匹配的用户;它无法利用以前检索过的"来自group_of_users = Data.objects.filter(...)
查询集的用户,因为此时没有实际检索到任何内容。
答案 2 :(得分:1)
您的方法完全正确且效率很高。在评估之前,Querysets不会触及数据库,因此您可以根据需要添加任意数量的过滤器,并且不会触及数据库。 Django's excellent documentation提供了确定哪些操作导致Queryset被评估所需的所有信息。