如何在 rails 中获得每个模型枚举的前 5 名?

How to get the top 5 per enum of a model in rails?

假设我有一个名为 post 的模型,它有一个名为 post_typeenum,它可以是 adminpublicuser

#app/models/post.rb

class Post < ApplicationRecord
 enum post_type: [ :admin, :public, :user ]
end

如何从每个类别中 select 5 个最近创建的帖子?

除此之外我想不出任何其他解决方案:

PER_GROUP = 5

admin_posts = Post.admin.order(created_at: :desc).limit(PER_GROUP)
user_posts = Post.user.order(created_at: :desc).limit(PER_GROUP)
public_posts = Post.public.order(created_at: :desc).limit(PER_GROUP)

有什么方法可以通过对数据库的单个查询以所需的方式获取所有行。

堆栈

RAILS : 6
PostgresSQL: 9.4

我不确定如何翻译成 RAILS,但它是直截了当的 Postgres 查询。您在子 select 中使用 row_number window 函数,然后只保留 row_number 小于或等于 5 的行在外部 select.

select *
  from (select post_txt
             , posted_type
             , row_number() over (partition by posted_type) rn
          from enum_table
       ) pt
 where rn <= 5 
 order by posted_type;

需要注意的一件事是枚举的排序。这样做会按照定义的顺序给出结果,而不是“自然顺序”(在本例中为字母数字)。参见 example here

多亏了@Belayer,我才能够想出一个解决方案。

PER_GROUP = 5

sub_query = Post.select('*', 'row_number() over (partition by "posts"."post_type" ORDER BY posts.created_at DESC ) rn').to_sql

@posts = Post.from("(#{sub_query}) inner_query")
             .where('inner_query.rn <= ?', PER_GROUP')
             .order(:post_type, created_at: :desc)
             .group_by(&:post_type)

因为我只加载 5 条不同类型的记录 group_by 对我来说很好。