【问题标题】:Controlling ordering of Django queryset result via filtering with redis list通过使用 redis 列表过滤来控制 Django 查询集结果的排序
【发布时间】:2016-07-25 20:31:54
【问题描述】:

在我的一个 Django 网站上,用户贡献了帖子,然后这些帖子在主页上全局显示,按最近的排序在前。

我通过将所有 post_ids 的lpush 加入到 redis 列表中来将 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 模板(即{% for post in object_list %} 中迭代context["object_list"],并一一填充最新帖子供我的用户查看。

我的问题是这种安排不会首先显示最近的。它总是最后显示最近的。所以我将lpush改为rpush但结果根本没有改变。为什么不改变redis的列表插入方法改变Django的查询集返回的结果的顺序我?

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

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

【问题讨论】:

    标签: django redis django-views django-queryset


    【解决方案1】:

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

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

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

    【讨论】:

    • 谢谢,这很有帮助 - 清除了我的概念。顺便说一句,redis 确实有帮助。对于这个特定的查询,我的服务器响应时间从 ~95ms 到 ~4ms。我想它因情况而异,但在我的情况下确实很神奇!再次感谢。
    猜你喜欢
    • 2019-08-08
    • 2013-04-20
    • 1970-01-01
    • 2016-11-30
    • 2017-06-18
    • 2012-10-05
    • 2016-02-19
    • 2011-10-19
    • 2014-12-13
    相关资源
    最近更新 更多