Django objects.filter 列表和每场比赛的 5 个实例

Django objects.filter with list and 5 instances from each match

我有一个场景,我有一个 属性 模型,它具有评级属性。 属性 模型有数千个不同评级的属性。我需要根据以下条件从数据库中检索属性,

1) 如果我有 rating_list = [5, 4, 1, 2, 3, unrated] 我知道我可以通过

轻松实现它
Property.objects.filter(rating__in=rating_list)[:50]

问题在于,由于我有数千个不同评级的属性,因此上述查询 returns 50 个属性可能只有 5 个评级,而我需要 10 个属性用于过滤器中的每个评级。

2) 另一个要求是我希望返回的结果与 rating_list 中给出的顺序完全相同。 例如,查询集应包含评级为 5 的前 10 个属性,接下来的 10 个属性为评级 4,下一个评级为 1,依此类推。

3) 由于我们有数千个属性,因此我们希望在单个查询中而不是在多个查询中完成。

是否有任何解决方案可以实现此目的或可能的解决方案。

您可以合并查询集,并限制该联合,例如:

Property.objects.filter(rating=5)[:10].union(
    Property.objects.filter(rating=4)[:10],
    Property.objects.filter(rating=1)[:10],
    Property.objects.filter(rating=2)[:10],
    Property.objects.filter(rating=3)[:10],
    Property.objects.filter(rating=<i>unrated</i>)[:10],
    all=True
)

通过使用 union,通常会遵守顺序。

.union 在单个查询中执行,SQL 将类似于:

          (SELECT * FROM appname_property WHERE rating=5 LIMIT 10)
UNION ALL (SELECT * FROM appname_property WHERE rating=4 LIMIT 10)
UNION ALL (SELECT * FROM appname_property WHERE rating=1 LIMIT 10)
UNION ALL (SELECT * FROM appname_property WHERE rating=2 LIMIT 10)
UNION ALL (SELECT * FROM appname_property WHERE rating=3 LIMIT 10)
UNION ALL (SELECT * FROM appname_property WHERE rating=<i>unrated</i> LIMIT 10)

由于过滤可能很昂贵,您可能需要在 rating 字段中添加 db_index=True [Django-doc]

class Property(models.Model):
    rating = models.IntegerField(<b>db_index=True</b>)