制定具有高度挑战性要求的高效数据库查询(Django应用程序)

时间:2015-11-08 07:15:47

标签: python django performance postgresql query-optimization

这是一个艰难的。我有一个基于django的网络应用程序,用户可以发布有趣的URL,并在每个帖子下有观众评论。此外,我使用stealth banning来防止行为不端用户。

有趣的网址由Link模型表示;发布的评论由Publicreply模型重新发布。

以下是这些模型之间的相互关系:

class Link(models.Model): 
    submitter = models.ForeignKey(User)
    submitted_on = models.DateTimeField(auto_now_add=True)
    url = models.URLField(max_length=250)

class Publicreply(models.Model):
    submitted_by = models.ForeignKey(User)
    answer_to = models.ForeignKey(Link)
    submitted_on = models.DateTimeField(auto_now_add=True)
    description = models.TextField(validators=[MaxLengthValidator(250)])

Users我禁止去这里:

class HellBanList(models.Model):
    condemned = models.ForeignKey(User)
    when = models.DateTimeField(auto_now_add=True)

我的问题是什么?我正在尝试编写性能最佳优化查询,这样我就可以了:

1。 publicreply在用户自己发布的所有不同links中具有绝对最新时间戳 FROM,或低于用户离开了publicreply

2。但是,如果{1}}对象中的publicreply对象属于HellBanList(即被谴责的属性),我会忽略该特定{ {1}}并挖掘下一个最新的。如果那也是被禁用的用户,我会跳到下一个(依此类推)。

3。最后,我只需要publicreply对象中的submitted_bysubmitted_on属性值,我最终只能满足1和2。

那么到目前为止我尝试了什么?这样:

publicreply

此代码有什么问题?事实上它不符合要求 2 。我想我应该以{{1​​}} freshest_link = Link.objects.filter(Q(submitter=self.request.user)|Q(publicreply__submitted_by=self.request.user)).distinct().annotate(date=Max('publicreply__submitted_on')).latest('date') freshest_reply = Publicreply.objects.filter(answer_to=freshest_link).latest('submitted_by') exclude() 发布publicreplys users之前计算HellBanList(按顺序)满足要求 2 )。无论如何我无法弄清楚如何做到这一点。其次,专家可以比我的尝试更有效地构建整个查询,目标是最小化数据库往返。

你可以帮帮忙吗?如果你觉得我在描述我想要实现的目标时一直不透明,那就请求澄清。

注意:我的数据库是postgres

1 个答案:

答案 0 :(得分:1)

获取禁止用户列表,如:

banlist = HellBanList.objects.values_list('condemned',flat=True)

修改freshest_reply查询,如:

freshest_reply = Publicreply.objects.filter(answer_to=freshest_link).exclude(submitted_by_id__in=banlist).latest('submitted_on')

第二种方法:

在您的查询中,首先您获得具有最新公开回复的Link,并在下一个查询中获得该Publicreply的最新Link。而不是我们可以在一个查询中获取最新的回复,如:

latest_reply = Publicreply.objects.filter(Q(answer_to__submitter=self.request.user)|Q(submitted_by=self.request.user)).exclude(submitted_by_id__in=banlist).latest('submitted_on')

如果我错过了什么,请告诉我。