当前位置: 首页 > 面试题库 >

如何在Django查询集中使用条件注释计数

邵伟
2023-03-14
问题内容

使用Django ORM,可以做类似的事情queryset.objects.annotate(Count('queryset_objects', gte=VALUE))。赶上我的漂移?

这是一个用于说明可能答案的快速示例:

在Django网站中,内容创建者提交文章,普通用户查看(即阅读)所述文章。文章可以发布(即供所有人阅读),也可以草稿模式发布。描述这些要求的模型是:

class Article(models.Model):
    author = models.ForeignKey(User)
    published = models.BooleanField(default=False)

class Readership(models.Model):
    reader = models.ForeignKey(User)
    which_article = models.ForeignKey(Article)
    what_time = models.DateTimeField(auto_now_add=True)

我的问题是:如何才能获得所有发表的文章,并按过去30分钟内的唯一读者排序?也就是说,我想计算每个已发布文章在过去半小时内获得多少个独特(唯一)视图,然后生成按这些独特视图排序的文章列表。

我试过了:

date = datetime.now()-timedelta(minutes=30)
articles = Article.objects.filter(published=True).extra(select = {
  "views" : """
  SELECT COUNT(*)
  FROM myapp_readership
    JOIN myapp_article on myapp_readership.which_article_id = myapp_article.id
  WHERE myapp_readership.reader_id = myapp_user.id
  AND myapp_readership.what_time > %s """ % date,
}).order_by("-views")

这会产生错误:语法错误在“ 01”或附近(其中“ 01”是多余的日期时间对象)。这没什么可继续的


问题答案:

对于Django> = 1.8
使用条件聚合:

from django.db.models import Count, Case, When, IntegerField
Article.objects.annotate(
    numviews=Count(Case(
        When(readership__what_time__lt=treshold, then=1),
        output_field=IntegerField(),
    ))
)

说明: 通过你的文章进行的常规查询将使用numviews字段注释。该字段将被构造为CASE / WHEN表达式(由Count包裹),对于符合NULL读者身份的条件和不符合条件的读者,将返回1 。计数将忽略空值,仅计数值。

对于近期未查看过的文章,你将得到零,并且可以使用该numviews字段进行排序和过滤。

PostgreSQL的查询如下:

SELECT
    "app_article"."id",
    "app_article"."author",
    "app_article"."published",
    COUNT(
        CASE WHEN "app_readership"."what_time" < 2015-11-18 11:04:00.000000+01:00 THEN 1
        ELSE NULL END
    ) as "numviews"
FROM "app_article" LEFT OUTER JOIN "app_readership"
    ON ("app_article"."id" = "app_readership"."which_article_id")
GROUP BY "app_article"."id", "app_article"."author", "app_article"."published"

如果我们只想跟踪唯一查询,则可以在中添加区分Count,并使When子句返回值,我们想区分。

from django.db.models import Count, Case, When, CharField, F
Article.objects.annotate(
    numviews=Count(Case(
        When(readership__what_time__lt=treshold, then=F('readership__reader')), # it can be also `readership__reader_id`, it doesn't matter
        output_field=CharField(),
    ), distinct=True)
)

这将产生:

SELECT
    "app_article"."id",
    "app_article"."author",
    "app_article"."published",
    COUNT(
        DISTINCT CASE WHEN "app_readership"."what_time" < 2015-11-18 11:04:00.000000+01:00 THEN "app_readership"."reader_id"
        ELSE NULL END
    ) as "numviews"
FROM "app_article" LEFT OUTER JOIN "app_readership"
    ON ("app_article"."id" = "app_readership"."which_article_id")
GROUP BY "app_article"."id", "app_article"."author", "app_article"."published"
对于django <1.8和PostgreSQL

你可以仅raw用于执行由django的较新版本创建的SQL语句。显然,没有一种简单而优化的方法可以在不使用数据的情况下查询该数据raw(即使extra注入必填JOIN子句存在一些问题)。

Articles.objects.raw('SELECT'
    '    "app_article"."id",'
    '    "app_article"."author",'
    '    "app_article"."published",'
    '    COUNT('
    '        DISTINCT CASE WHEN "app_readership"."what_time" < 2015-11-18 11:04:00.000000+01:00 THEN "app_readership"."reader_id"'
    '        ELSE NULL END'
    '    ) as "numviews"'
    'FROM "app_article" LEFT OUTER JOIN "app_readership"'
    '    ON ("app_article"."id" = "app_readership"."which_article_id")'
    'GROUP BY "app_article"."id", "app_article"."author", "app_article"."published"')


 类似资料:
  • 问题内容: 我有两个表,一个表用于新闻,另一个表用于评论,我想获取其状态已设置为批准的评论数。 但是此查询的问题在于,无论是否存在与该新闻相对应的评论,为评论列获取的最小值为1。 任何帮助将是非常可贵的。 问题答案: 使用代替 请尝试以下方法:

  • 问题内容: 考虑简单的Django模型和: 使用参与者总数来注释事件查询很容易: 如何用筛选的参与者计数进行注释? 我需要查询所有事件,而与参与者人数无关,例如,我不需要按带注释的结果进行过滤。如果有参与者,那没关系,我只需要带有0注释的值即可。 文档中的示例在这里不起作用,因为它从查询中排除了对象,而不是使用注释了对象0。 更新。Django 1.8具有新的条件表达式功能,因此我们现在可以像这样

  • 问题内容: 我有点困惑如何使用在Django的。例如,一个对象Blog ,以及与该对象相关的attribute entry_set。是什么意思? 如果有人可以使用此示例显示可能的输出,我将不胜感激。 问题答案: 你看到的是反向相关的对象查找。 在你的示例中: 现在,给定类型为的对象,你将可以访问相关对象-这是一个正向关系。该是一个反向查找类变量的Django为你看跌期权。 因此,给定对象-你将执行

  • 问题内容: 这是我目前最喜欢使用的一项前沿功能,并且很快就会消失。我想将子查询聚合注释到现有查询集上。在1.11之前执行此操作意味着自定义SQL或修改数据库。这是this的文档以及其中的示例: 他们在总体上进行注释,这对我来说似乎很奇怪,但是无论如何。 我正在为此而苦苦挣扎,所以我将其沸腾回到我拥有数据的最简单的真实示例中。我有,其中包含许多Space。使用会使你更快乐,但是-暂时-我仅想使用 注

  • 我正在尝试创建一个查询并根据自定义权重计算对其进行排序。 我需要一些帮助作为解决方案我来确实工作但性能是不是在那里我想它是 我拥有的是一个媒体对象。它有相关的评论、喜欢和命令。 以下查询目前有效,但完全是一团乱麻: 如您所见,我正在单独注释我将使用的所有参数,然后对查询集中的每个项目进行愚蠢的遍历,这是非常次优的。 我尝试做的一件事是: 但是注释中的类似操作是不可能的(尝试了一些有和没有Sum()

  • 问题内容: 我正在使用MongoRepository将Spring Data与MongoDB结合使用。 我想知道是否有可能使用查询注释通过过滤器进行删除。我一直在这里和谷歌,我找不到任何文档。 问题答案: