所以我正在开发一个rails应用程序,我正在研究分页Feed。当我这样做时,我想知道我是否正确地做到了这一点,因为我的加载时间超过了1500毫秒。我的代码是:
stories = Story.feed
@stories = Kaminari.paginate_array(stories).page(params[:page]).per(params[:pageSize])
我对此有几个问题:
Story.feed
,还是有某种方法
只返回一些我需要的故事?(另外,Story.feed返回一个故事对象数组。代码在这里:
def self.feed
rawStories = Story.includes([:likes, :viewers, :user, :storyblocks]).all
newFeaturedStories = rawStories.where(:featured => true).where(:updated_at.gte => (Date.today - 3)).desc(:created_at).entries
normalStories = rawStories.not_in(:featured => true, :or => [:updated_at.gte => (Date.today - 3)]).desc(:created_at).entries
newFeaturedStories.entries.concat(normalStories.entries)
end
我正在使用mongoid和mongodb
答案 0 :(得分:0)
我怀疑当你在Kaminari.paginate_array
上调用ActiveRecord::Relation
时,它会导致整个结果集从数据库中获取并加载到内存中,类似于调用Model.all.to_a
。
为了避免这种情况,我首先找到一种方法将Story.feed
转换为范围,而不是类方法。从表面上看,它们看起来是一样的 - 差异是微妙而深刻的。请参阅Active Record scopes vs class methods。
接下来,放弃paginate_array
支持链Kaminari的page()
和per()
范围。
例如(你的简化版):
class Article < ActiveRecord::Base
scope :featured, -> { where(featured: true) }
scope :last_3_days, -> { where(:updated_at.gte => (Date.today - 3)).desc(:created_at) }
scope :feed, -> { featured.last_3_days }
然后简单地通过:
分页Article.feed.per(page_size).page(page)
这方面的最大优点是Kaminari可以链接到生成的SQL中插入正确的LIMIT
和OFFSET
子句,从而减少返回到只需要显示的结果集的大小,如反对返回每个匹配的记录。
答案 1 :(得分:0)
问题是您从数组中获取db的所有提要,这需要很长时间。
我建议您使用any_of
查询from this great gem。
从那里开始:
def self.feed_stories
newFeaturedStories = Story.where(:featured => true).where(:updated_at.gte => (Date.today - 3.days))
normalStories = Story.not_in(:featured => true, :or => [:updated_at.gte => (Date.today - 3.days)])
Story.includes([:likes, :viewers, :user, :storyblocks]).any_of(newFeaturedStories, normalStories).desc(:created_at)
end
然后分页:
selected_stories = Story.feed_stories.per(page_size).page(page)
不要真正理解你的entries
是什么,而是在这一刻得到它们。
总结一下:创建一个独特的分页数据库查询。
答案 2 :(得分:-1)
我认为Will Paginate会帮助你 - &gt; mislav/will_paginate。 从那里你可以简单地给你的控制器动作.per_page(20)例如在20个对象之后(你可以定义对象,参见wiki)会有分页