【问题标题】:Django objects.filter with list and 5 instances from each matchDjango objects.filter,每个匹配项包含列表和 5 个实例
【发布时间】:2020-09-05 09:01:58
【问题描述】:

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

1) 如果我有一个 rating_list = [5, 4, 1, 2, 3, unrated] 我知道我可以通过这样做轻松实现它

Property.objects.filter(rating__in=rating_list)[:50]

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

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

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

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

【问题讨论】:

  • 可以分享一下相关模型吗?
  • @WillemVanOnsem 只有一个具有评级属性的属性模型,我想使用该评级属性进行过滤。上面提到了过滤器的标准。

标签: python django python-3.x django-models django-orm


【解决方案1】:

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

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=unrated)[: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=unrated LIMIT 10)

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

class Property(models.Model):
    rating = models.IntegerField(db_index=True)

【讨论】:

  • 感谢它为我工作的解决方案,但如果您查看第三个标准,我需要以与我的 rating_list 相同的顺序检索列表,这不是 ASC 或 DESC 顺序。我们可以在同一个查询中做到这一点吗?
  • @UsmanHussain:我们以相同的顺序检索它,注意rating= 过滤器的顺序,首先我们过滤54,然后是1,等等。(最初的答案是 DESC,因为不知何故我知道您正在寻找它)。
  • @UsmanHussain:不行的原因是切片后大部分子句都不适用了。
  • @UsmanHussain:如果你使用Property.objects.filter(rating=5).values_list("id", "giata_id__provider_ref")[:10].union(...) 会怎样(所以每次在切片之前使用.values_list)?
  • @UsmanHussain:如果性能是一个问题,那么确实使用.values_list 会更好,因为那时您将数据库中的数据量限制在 Python/Django 级别。
猜你喜欢
  • 1970-01-01
  • 2021-08-18
  • 2017-08-19
  • 1970-01-01
  • 1970-01-01
  • 2011-08-22
  • 1970-01-01
  • 1970-01-01
  • 2010-10-28
相关资源
最近更新 更多