Python 获取查询集中元素的索引
我有一个查询集,我们称之为Python 获取查询集中元素的索引,python,django,indexing,django-queryset,Python,Django,Indexing,Django Queryset,我有一个查询集,我们称之为qs,它是由一些与这个问题无关的属性排序的。然后我有一个对象,我们称它为obj。现在我想知道obj在qs中的索引是什么,尽可能高效。我知道我可以使用Python中的.index(),或者可能通过qs循环,将每个对象与obj进行比较,但是最好的方法是什么?我在寻找高性能,这是我唯一的标准 在Windows上将Python 2.6.2与Django 1.0.2结合使用。Django中的查询集实际上是生成器,而不是列表(有关详细信息,请参阅)。 因此,获取元素的索引没有捷径,
qs
,它是由一些与这个问题无关的属性排序的。然后我有一个对象,我们称它为obj
。现在我想知道obj
在qs
中的索引是什么,尽可能高效。我知道我可以使用Python中的.index()
,或者可能通过qs
循环,将每个对象与obj
进行比较,但是最好的方法是什么?我在寻找高性能,这是我唯一的标准
在Windows上将Python 2.6.2与Django 1.0.2结合使用。Django中的查询集实际上是生成器,而不是列表(有关详细信息,请参阅)。
因此,获取元素的索引没有捷径,我认为简单的迭代是最好的方法 对于初学者,我将以最简单的方式实现您的需求(如迭代);如果您确实存在性能问题,那么我将使用一些不同的方法,例如使用较少的字段构建查询集,或者其他任何方法。
在任何情况下,我们的想法都是在你明确知道自己需要这些技巧的时候,尽可能晚地放弃这些技巧。
更新:您可能希望直接使用一些SQL语句来获取行数(有些错误。但是,Django的ORM本机不支持此操作,您必须使用原始SQL查询(请参阅)。我认为这可能是最好的选择,但同样-只有当您真正看到一个真正的性能问题时。如果您已经在迭代queryset,并且只想知道当前所在元素的索引,那么紧凑且可能最有效的解决方案是:
for index, item in enumerate(your_queryset):
...
但是,如果您有一个queryset和一个通过一些不相关的方式获得的对象,并且希望了解该对象在queryset中的位置(如果它在那里的话),请不要使用它。为了说明的目的,假设您的模型是带有主键
id
的标准模型,然后进行评估
list(qs.values_list('id', flat=True)).index(obj.id)
将在
qs
中找到obj
的索引。虽然使用list
计算查询集,但它不会计算原始查询集,而是计算派生查询集。此计算仅运行SQL查询以获取id字段,而不会浪费时间获取其他字段。如果您只想知道对象在所有字段中的位置其他(例如,在确定等级时),您可以通过计算前面的对象来快速完成:
index = MyModel.objects.filter(sortField__lt = myObject.sortField).count()
您可以使用和一些原始SQL这样做:
queryset = queryset.order_by("id")
record500 = queryset[500]
numbered_qs = queryset.extra(select={
'queryset_row_number': 'ROW_NUMBER() OVER (ORDER BY "id")'
})
from django.db import connection
cursor = connection.cursor()
cursor.execute(
"WITH OrderedQueryset AS (" + str(numbered_qs.query) + ") "
"SELECT queryset_row_number FROM OrderedQueryset WHERE id = %s",
[record500.id]
)
index = cursor.fetchall()[0][0]
index == 501 # because row_number() is 1 indexed not 0 indexed
一种简单的python方法可以查询queryset中元素的索引:
(*qs,).index(instance)
这个答案将把queryset解压到一个列表中,然后使用内置的Python索引函数来确定它的位置。我明白了。我上次接触SQL已经有一段时间了,但我想可能在普通SQL中也可以,因此可以使用Django的queryset API。是的,这可能是一个选项。我已经将它添加到了可能的so中解析。这可能比仅评估原始查询集更有效,也可能效率更低,这取决于您以后是否要这样做(因为查询集缓存其结果)。此方法存在问题。qs.values\u list('id',flat=True)在每个步骤中返回不同的值。使用相同的查询可以获得不同的索引。在这种情况下,您还希望
sortField
是唯一的,因为否则您将获得sortField
等于myObject.sortField
的第一个元素的位置。它是否应该是.count()-1
?例如,如果查询集中有1个对象,则索引为0。@david。在这种情况下,表达式将给出0作为计数,因为过滤器使用的是“小于”而不是“小于或等于”。@alexche8它在1000个结果集中的10个结果集上表现得足够好(我随后分页)就更新而言,首先,查询集是无序的。因此,索引可能会因不同的迭代而有所不同。您需要对任何字段执行order\by
,然后如果您只需要索引,则遵循Vinay的答案将有助于解决问题。如果我们有1000万条记录,则数据库很难操作。这是没有效率的,而且存在内存泄漏由于您正在从python代码中循环遍历表中的每个对象,因此这是一个非常棘手的问题。最有效的答案是使用单个DB查询来获取索引,该索引是Richard的索引answer@Amin_mmz这取决于海报想要什么。如果他们在queryset上迭代,就拥有一个对象并想知道它的位置-enumerate
就是他们所需要的。这是我对这个问题的理解,也是为什么没有循环体的原因。但是,我发现它可以有不同的解释。如果他们有一个queryset和一个他们认为包含在其中的对象-你是对的,迭代queryset是一个糟糕的想法,Richard的答案是正确的。更好的查询可以是使用SQLROW\u NUMBER()
window函数的查询。