ruby-on-rails - 预加载 : The right way to do things

标签 ruby-on-rails ruby database ruby-on-rails-3 eager-loading

我正在运行 Ruby on Rails 3.1。我阅读了以下关于eager loading 的文章和文档,我想找到一种正确的方法来做事:

  1. Eager Loading Associations [官方文档]
  2. ActiveRecord::Associations::ClassMethods (参见“关联的预加载”部分)[官方文档]
  3. Eager loading [博客文章]

#2 说:

Note that using conditions like Post.includes([:author, :comments]).where(['comments.approved = ?', true]).all can have unintended consequences.

#3 说那些意想不到的后果是(注意:示例非常相同,所以我引用了博客文章的确切文本,但你必须保持注意解决方法,而不是具体的实现):

This query, since it would use a LEFT JOIN, would also discard all posts without a comment with the word “first” on any of it’s comments.

即如果有非“关联”对象,则不会加载“主关联”对象。这是当我尝试通过添加一些条件来使用预加载时发生的情况,例如 .where(:category_relationships => {:user_id => @current_user.id})我的previous question ,但我不希望这种情况发生。

所以(失败者因为我可能无法在 condition 无法在 has_many 语句中设置的情况下使用预加载 - 请注意,在上面的代码中@current_user.id 是“动态设置”的,这与提到的站点中的示例不同),我想知道是否有 pratiques/techniques/strategies 来限制数据库查询,因为我有“N + 1 个问题”

也许这些实践/技术/策略完全可以通过使用 Ruby on Rails 框架来实现……#1 说:

Even though Active Record lets you specify conditions on the eager loaded associations just like joins, the recommended way is to use joins instead.

什么以及如何以正确的方式解决这个问题?


也许一个解决方案是通过运行特定的和单独的数据库查询来检索和构建自己需要加载的内容,但是问题将是如何“传递”/“关联”/“插入”那些检索到的内容“associated”对象到“main associated”对象,以便可以使用“预加载”方式? 也就是说,如何使(有关更多信息,请参阅 mentioned question)使用像 @article.comments 并只获取我自己急切加载的评论?在 my eager loading 之后,可能/正确 制作类似 @article.comments = my_eager_loaded_comments 这样的东西吗对文章“传递”/“关联”/“插入”评论?

最佳答案

After my eager loading, is it possible / correct to make something like @article.comments = my_eager_loaded_comments so to "pass"/"associate"/"interpolate" comments to articles?

是的,这是可能的。我经常这样做。

请注意,我的解决方案仍会从数据库中检索所有关联对象。如果您的条件是动态的,我认为没有任何解决方案可以仅检索过滤后的关联对象。我的解决方案侧重于过滤检索到的关联对象。

我假设要求是获取文章列表,并且在每篇文章中,只加载一个特定用户的评论

文章模型中:

def self.get_articles_with_comments_of_user( article_ids, user_id )
  articles = Article.where( id: article_ids ).includes( :comments )

  articles.each do |article|
    filtered_comments = article.comments.select { |comment| comment.user_id == user_id }
    article.association("comments").target = filtered_comments
  end

  articles
end

在上述方法返回的文章集合中,评论关联将只包含该特定用户的评论。

我希望这就是您所要求的。

关于ruby-on-rails - 预加载 : The right way to do things,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9642900/

相关文章:

ruby-on-rails - uploader 产生关于它应该存储路径的列的错误

ruby-on-rails - Railstutorial : db:populate vs. 工厂女孩

PHP 在两个字符串之间选择

javascript - Angular promise 在服务中的响应问题

ruby-on-rails - Elasticsearch 6.2.4 [400] {“error”:{“root_cause”:[{“type” :“illegal_argument_exception” ,“reason” :“text is empty (possibly HTTP/0.9)”}]

ruby-on-rails - 如何使用 Rails 主动存储从 url 保存图像?

Ruby Mongo Driver 2.0.0 连接状态

MySQL - 如何计算每行和字段的差异?

mysql - Magento 2 安装失败 - SQLSTATE[HY000] [1045] 用户访问被拒绝

ruby-on-rails - 仅显示所选类别的子类别