Ruby on rails ';拆分';ActiveRecord集合
假设我有两个模型,分别是Post和Category:Ruby on rails ';拆分';ActiveRecord集合,ruby-on-rails,ruby,database,activerecord,Ruby On Rails,Ruby,Database,Activerecord,假设我有两个模型,分别是Post和Category: class Post < ActiveRecord::Base belongs_to :category end class Category < ActiveRecord::Base has_many :posts end 换句话说,按选定的类别ID将所有帖子的集合“拆分”为数组当然,但考虑到您的模型关系,我认为您需要从另一个角度来看待它 p = [] 1.upto(some_limit) do |n| post
class Post < ActiveRecord::Base
belongs_to :category
end
class Category < ActiveRecord::Base
has_many :posts
end
换句话说,按选定的类别ID将所有帖子的集合“拆分”为数组当然,但考虑到您的模型关系,我认为您需要从另一个角度来看待它
p = []
1.upto(some_limit) do |n|
posts = Category.posts.find_by_id(n)
p.push posts if posts
end
类似的方法可能会起作用(Post的实例方法,未经测试):
def按类别拆分(*id)
自注入([])do | arr,p|
arr[p.category_id]| |=[]
arr[p.category\u id]在Array
类上尝试group\u by
功能:
posts.group_by(&:category_id)
有关更多详细信息,请参阅API
注意事项:
当潜在数据集可能很大时,不应在Ruby代码中执行分组。当最大可能的数据集大小<1000时,我使用groupby
函数。在您的情况下,您可能有1000个Post
s。处理这样一个数组会给您的资源带来压力。依靠数据库执行分组/排序/聚合等
下面是一种方法(类似的解决方案由nas
建议)
与其获取所有帖子,然后对它们进行一些操作以对它们进行分类,这是一个性能密集型的练习,我更愿意像这样使用即时加载
categories = Category.all(:include => :posts)
这将生成一个sql查询来获取所有文章和类别对象。然后,您可以轻松地对其进行迭代:
p = Array.new
categories.each do |category|
p[1] = category.posts
# do anything with p[1] array of posts for the category
end
是的,但这样它将运行一些限制SQL查询,如果可能的话,我只想使用一个查询(posts=Post.find(:all))。@nas这将返回没有posts的类别。你必须添加额外的条件来过滤没有帖子的类别。@Kandaboggu我认为你是否得到没有帖子的类别并不重要,因为根据问题@Vincent正在对帖子而不是类别进行操作。当您调用category.posts
时,您将得到一个空数组,在空数组中迭代不会执行代码块,因此没有效果。因此,根据场景,这里不需要任何条件。因为帖子有类别,@Vincent的逻辑不必处理没有帖子的类别场景。最好通过添加附加条件在DB级别过滤掉空类别。@Kandaboggu对不起,帖子没有类别;类别有职位,职位属于类别。为什么你认为@Vincent的逻辑必须处理没有帖子的类别场景?请你再看一次我之前的评论好吗?posts
表中有一列名为category\u id
。每个帖子都有一个类别,一个类别可能有帖子,也可能没有帖子。我的观点是消除DB查询中的空类别,而不是ruby代码中的空类别。这将减少SQL返回的categories结果集大小,并加快延迟获取查询的速度。“group_by”解决方案正是我想要的,谢谢!
# returns the categories with at least one post
# the posts associated with the category are pre-fetched
Category.all(:include => :posts,
:conditions => "posts.id IS NOT NULL").each do |cat|
cat.posts
end
categories = Category.all(:include => :posts)
p = Array.new
categories.each do |category|
p[1] = category.posts
# do anything with p[1] array of posts for the category
end