【问题标题】:Fetch list of records with bookmark status获取具有书签状态的记录列表
【发布时间】:2017-07-26 11:55:29
【问题描述】:

我有一个应用程序,用户可以在其中为帖子添加书签。为了处理书签,我创建了一个名为 Bookmark 的多态模型。

现在我需要显示所有帖子的列表(假设每页 50 个,分页),并为当前登录的用户显示标题和书签状态。

我脑子里有两个场景,我该如何实现这一点。而且我一个都不喜欢。

  1. 在呈现列表时检查每个帖子的书签状态 - 这会产生 N+1 查询,总的来说基本上是一个可怕的想法
  2. 获取当前页面的帖子 ID 列表,获取当前用户 bookmarkable_id IN post_ids_of_current_page 的所有书签,检查可书签列表中存在的帖子并根据此显示书签状态。

这一秒很合理,但我真的很想将它全部合并到一个 SQL 查询(如果可能,我不确定是否可以使用 joins 来完成)。这是因为事实上,我没有在常规的 Rails 视图中使用它,而是在 graphql API 端点 + SPA 应用程序中使用它,并且获取集合 ID 并比较它们并不是那么简单。它只会导致对 api 的大量请求,我希望避免。

【问题讨论】:

    标签: sql ruby-on-rails activerecord


    【解决方案1】:

    事实证明,我可以为此使用includes 方法(这将产生两个查询,但仍然比 N+1 好)。如果有人可以与joins 共享一个查询版本,我将非常乐意接受它的答案,但到目前为止,我发布的解决方案足以满足我的需求。

    class User
      has_many :bookmarks, as: :bookmarker
    end
    
    class Post
      has_many :bookmarks_as_bookmarkable, as: :bookmarkable, class_name: :Bookmark
    
      def bookmarked_by?(bookmarker)
        self.bookmarks_as_bookmarkable.to_a.select do |b|
          b.bookmarker_type == bookmarker.class.name &&
          b.bookmarker_id   == bookmarker.id
        end.any?
      end
    end
    

    结果:

    Post.includes(:bookmarks_as_bookmarkable).map { |p| u.bookmarked_by?(current_user) }`  
    # SELECT "posts".* FROM "posts"
    # SELECT "bookmarks".* FROM "bookmarks" WHERE "bookmarks"."bookmarkable_type" = ? AND "bookmarks"."bookmarkable_id" IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30)
    #
    # => [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-18
      • 2015-07-14
      • 2020-05-05
      相关资源
      最近更新 更多