postgresql Django:快速检索 manyToMany 字段的 ID
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17388254/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Django: Retrieving IDs of manyToMany fields quickly
提问by Noah Gilmore
I have the following model schema in Django (with Postgres).
我在 Django 中有以下模型模式(使用 Postgres)。
class A(Models.model):
related = models.ManyToManyField("self", null=True)
Given a QuerySet of A, I would like to return a dictionary mapping each instance of A
in the QuerySet to a list of id
s of its related
instances as quickly as possible.
给定 A 的 QuerySet,我想尽快返回一个字典A
,将 QuerySet 中的每个实例映射到id
其related
实例的s列表。
I can surely iterate through each A and query the related field, but is there a more optimal way?
我当然可以遍历每个 A 并查询相关字段,但是有没有更优化的方法?
回答by Luan Fonseca
According you have Three instances. You can use the values_list
method to retrieve just the results and from this result get just the ID's of their related
instances.
I use the pk
field to be my filter because i don't know your scheme, but you can use anything, just must be a QuerySet
.
根据你有三个实例。您可以使用该values_list
方法仅检索结果,并从该结果中仅获取其related
实例的 ID 。我使用该pk
字段作为我的过滤器,因为我不知道您的方案,但是您可以使用任何内容,但必须是QuerySet
.
>>> result = A.objects.filter(pk=1)
>>> result.values('related__id')
[{'id': 2}, {'id': 3}]
>>> result.values_list('related__id')
[(2,), (3,)]
>>> result.values_list('related__id', flat=True)
[2, 3]
回答by DylanYoung
You can get pretty close like this:
你可以像这样接近:
qs = A.objects.prefetch_related(Prefetch(
'related',
queryset=A.objects.only('pk'),
to_attr='related_insts')).in_bulk(my_list_of_pks)
This will give a mapping from pks of the current object to the instance itself, so you can iterate through as follows:
这将给出从当前对象的 pks 到实例本身的映射,因此您可以按如下方式进行迭代:
for pk, inst in qs.iteritems():
related_ids = (related.pk for related in inst.related_insts)
Or given an instance, you can do a fast lookup like so:
或者给定一个实例,您可以像这样进行快速查找:
related_ids = (related.pk for related in qs[instance.pk]).
This method maps the instance ids to the related ids (indirectly) since you specifically requested a dictionary. If you aren't doing lookups, you may want the following instead:
此方法将实例 ID 映射到相关 ID(间接),因为您特别请求了字典。如果您不进行查找,则可能需要以下内容:
qs = A.objects.prefetch_related(Prefetch(
'related',
queryset=A.objects.only('pk'),
to_attr='related_insts')).filter(pk__in=my_list_of_pks)
for inst in qs:
related_ids = (related.pk for related in inst.related_insts)
You may take note of the use of only
to only pull the pks from the db. There is an open ticketto allow the use of values
and (I presume) values_list
in Prefetch queries. This would allow you to do the following.
您可能会注意到使用only
仅从数据库中提取 pks。有一个开放票允许在预取查询中使用values
和(我认为)values_list
。这将允许您执行以下操作。
qs = A.objects.prefetch_related(Prefetch(
'related',
queryset=A.objects.values_list('pk', flat=True),
to_attr='related_ids')).filter(pk__in=my_list_of_pks)
for inst in qs:
related_ids = inst.related_ids
You could of course optimize further, for example by using qs.only('related_insts')
on the primary queryset, but make sure you aren't doing anything with these instances-- they're essentially just expensive containers to hold your related_ids.
您当然可以进一步优化,例如通过qs.only('related_insts')
在主查询集上使用,但请确保您没有对这些实例做任何事情——它们本质上只是用于保存您的 related_ids 的昂贵容器。
I believe this is the best that's available for now (without custom queries). To get to exactly what you want, two things are needed:
我相信这是目前最好的(没有自定义查询)。为了得到你想要的东西,需要做两件事:
- The feature above is implemented
values_list
is made to work with Prefetchto_attr
like it does for annotations.
- 上面的功能实现了
values_list
与 Prefetch 一起使用,to_attr
就像注释一样。
With these two things in place (and continuing the above example) you could do the following to get exactly what you requested:
有了这两件事(并继续上面的示例),您可以执行以下操作以准确获得您的要求:
d = qs.values_list('related_ids', flat=True).in_bulk()
for pk, related_pks in d:
print 'Containing Objects %s' % pk
print 'Related objects %s' % related_pks
# And lookups
print 'Object %d has related objects %s' % (20, d[20])
I've left off some details explaining things, but it should be pretty clear from the documentation. If you need any clarification, don't hesitate!
我已经省略了一些解释事情的细节,但从文档中应该很清楚。如果您需要任何说明,请不要犹豫!