通过使用redis列表进行过滤来控制Django查询集结果的排序

时间:2016-07-25 20:31:54

标签: django redis django-views django-queryset

在我的Django网站上,用户提供帖子,然后在主页上全局显示,按最近的排序排序。

我正在将redis引入此混合中,方法是将所有post_id lpush放入redis列表(在1000个条目中保留修剪)。代码是:

def add_post(link_id):
    my_server = redis.Redis(connection_pool=POOL)
    my_server.lpush("posts:1000", link_id)
    my_server.ltrim("posts:1000", 0, 9999)

然后,当用户请求主页的内容时,我只需在相关的基于类的视图的get_queryset方法中执行以下查询:

Post.objects.filter(id__in=all_posts())

all_posts()只是:

def all_posts():
    my_server = redis.Redis(connection_pool=POOL)
    return my_server.lrange("posts:1000", 0, -1)

接下来,我在Django模板中迭代context["object_list"](即{% for post in object_list %},然后逐个填充最新帖子供我的用户查看。

我的问题是这种安排最近没有显示最近的。它总是显示最近的最后一次。所以我将lpush更改为rpush而不是,但结果根本没有改变。为什么不更改redis'list insert方法更改结果的排序Django的queryset正在回复我?

也许我错过了一些不成熟的东西。请告诉我发生了什么,以及如何解决这个问题({% for post in object_list reversed %}我唯一的选择)。我采用redis路线的原因当然是性能。在redis之前,我会这样做:Post.objects.order_by('-id')[:1000]提前致谢。

注意:如果需要,请询问更多信息

1 个答案:

答案 0 :(得分:0)

您正在浏览一个没有order_by条款的查询集,这意味着您对订单或结果没有任何期望。 __in子句只控制要返回的行,而不是它们的顺序。

返回的结果是id顺序的事实是一个实现细节。如果您想依赖它,您可以按相反顺序遍历查询集。一个更强大的解决方案是根据Redis返回的id的顺序重新排序(在Python中)实例。

尽管如此,我并不认为在这里使用Redis会有任何性能优势。我认为任何具有id索引的关系数据库都能够非常有效地执行Post.objects.order_by('-id')[:1000]。 (请注意,对查询集进行切片会对数据库执行LIMIT;您不会将所有行都提取到Python中,然后切换一个巨大的列表。)