通过使用 redis 列表进行过滤来控制 Django 查询集结果的排序
Controlling ordering of Django queryset result via filtering with redis list
在我的 Django 网站上,用户贡献帖子,然后在主页上全局显示,按最新排序。
我将 redis 引入到这个组合中,方法是将所有 post_ids 中的 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)
然后,当用户请求主页的内容时,我只需在相关class 视图的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]
提前致谢。
注意:如有需要请询问。
您正在遍历一个没有 order_by
子句的查询集,这意味着您不能对顺序或结果有任何期望。 __in
子句只控制 哪些 行到 return,而不是它们的顺序。
returned 结果按 id
顺序排列的事实是一个实现细节。如果你想依赖它,你可以以相反的顺序遍历查询集。一个更强大的解决方案是根据从 Redis returned 的 id 的顺序重新排序(在 Python 中)实例。
尽管如此,我认为在此处使用 Redis 不会有任何性能优势。我认为任何具有 id
索引的关系数据库都能够非常有效地执行 Post.objects.order_by('-id')[:1000]
。 (请注意,对查询集进行切片会对数据库执行 LIMIT
;您不会将所有行提取到 Python 中,然后对一个巨大的列表进行切片。)
在我的 Django 网站上,用户贡献帖子,然后在主页上全局显示,按最新排序。
我将 redis 引入到这个组合中,方法是将所有 post_ids 中的 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)
然后,当用户请求主页的内容时,我只需在相关class 视图的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]
提前致谢。
注意:如有需要请询问。
您正在遍历一个没有 order_by
子句的查询集,这意味着您不能对顺序或结果有任何期望。 __in
子句只控制 哪些 行到 return,而不是它们的顺序。
returned 结果按 id
顺序排列的事实是一个实现细节。如果你想依赖它,你可以以相反的顺序遍历查询集。一个更强大的解决方案是根据从 Redis returned 的 id 的顺序重新排序(在 Python 中)实例。
尽管如此,我认为在此处使用 Redis 不会有任何性能优势。我认为任何具有 id
索引的关系数据库都能够非常有效地执行 Post.objects.order_by('-id')[:1000]
。 (请注意,对查询集进行切片会对数据库执行 LIMIT
;您不会将所有行提取到 Python 中,然后对一个巨大的列表进行切片。)