如何为每个给定的外键列表获取 n 项?

Posted

技术标签:

【中文标题】如何为每个给定的外键列表获取 n 项?【英文标题】:How do I get n items for each of the given list of foreignkey? 【发布时间】:2018-07-31 22:10:48 【问题描述】:

我正在尝试找出一种在尽可能短的时间内执行此查询的方法。

number_of_results = 25
results = []
foreign_keys = [1,2,3,4,5]
for key in foreign_keys():
    results.append(Model.objects.filter(foreign_key=key)[:number_of_resutlts])

即使是单个查询集,也没关系。我想要完成的是减少数据库查询的数量。我的数据库是 PostgreSQL 10。

如何进一步简化这一点?

【问题讨论】:

.filter(foreign_key__in=[1,2,3,4,5]) 呢? @gogaz 为每个键返回n结果吗? __in 将为您提供所有具有 foreign_key 为 1,2,3,4,5 的模型对象 它的分组依据和限制结果集。我认为没有一个步骤可以通过 Django 实现这一目标。 @NihalSharma 原始 sql 怎么样? 【参考方案1】:

试试这个:

results.append(Model.objects.filter(foreign_key__in=key)[:number_of_resutlts])

【讨论】:

【参考方案2】:

这是一个group by and select n 问题。

似乎没有单步操作可以通过 Django 实现这一点。但是,使用联合,我们可以通过单个查询来访问数据库以获取结果。联合内部有自己的成本 - 单独运行查询并选择不同的等。

一种方法是使用原始 sql:

objs = Model.objects.raw(
                """SELECT rank_filter.* FROM (SELECT model.*, rank() 
                OVER (PARTITION BY foreign_key_id ORDER BY created DESC) 
                FROM model WHERE foreign_key_id IN (1,2,3,4,5)) 
                rank_filter WHERE RANK <= n""") # replace n with 25

for obj in objs:
    # do something

【讨论】:

【参考方案3】:

从 Django 1.11 开始,您可以在这种情况下使用 QuerySet 的union 方法:

qs = Model.objects.filter(foreign_key=foreign_keys[0])[:number_of_results]

for fk in foreign_keys[1:]:
    qs = qs.union(Model.objects.filter(foreign_key=fk)[:number_of_results])

https://docs.djangoproject.com/en/1.11/ref/models/querysets/#union

【讨论】:

Union 会触发个别查询,不是吗? 不,它会生成一个查询。 是的,一个查询里面有多个联合。检查过了。

以上是关于如何为每个给定的外键列表获取 n 项?的主要内容,如果未能解决你的问题,请参考以下文章

我应该索引一个经常更新的外键吗

Django - 如何为模型的外键制作表单?

当主键列是mysql中不同表的外键时,如何将主键列更改为自动递增

映射到多个主键的外键列

使用 Django,如何添加引用同一个表的外键列? [复制]

对数据集市中的外键列使用 NULL 是不是有任何性能影响