Rails 使用 Graphql + Searchkick 的 N+1 问题

brookepowell · 2020年04月13日 · 最后由 brookepowell 回复于 2020年04月13日 · 3367 次阅读

决定在项目中使用 Graphql 后,发现网上大多都是基于关系数据库做的项目, 可以参考的基于 elasticsearch 的项目不多bluedoc算一个,但也只是仅用于搜索功能。

我的项目获取数据是基于 searchkick,查询结果的 N+1 问题并不能使用基于ActiveRecord::Associationsgraphql-batch这样的 gem 解决。

请问有没有同学有这方面经验做一下指点?

hooopo 回复

谢谢回复,我试了一下这个 gem, 在我的 PostType 里面,当objectSearchkick::HashWrapper的实例的时候 (searchkick 搜索结果),batchloader 没有起作用,每条 post 还是单独 select 它的所有图片。

相关代码:

# demo_schema.rb
class DemoSchema < GraphQL::Schema
  mutation ::Types::MutationType
  query ::Queries::QueryType
  use BatchLoader::GraphQL
end

# post_type.rb
module Types
  class PostType < BaseObject
    field :id, String, null: false
    field :title, String, "标题", null: false
    field :images, [Types::ImageType], "图片", null: true

    def images
      # 这里的object是 Searchkick::HashWrapper
      BatchLoader.for(object.id).batch(default_value: []) do |post_ids, loader|
        Image.where(post_id: post_ids).each { |i| loader.call(i.post_id, i) }
      end
    end
  end
end

请教是我的使用方法有问题吗?

hooopo 回复

确实是使用方法的问题,在 Graphql 里应该调用 BatchLoader::GraphQL.for 现在可以了,非常感谢。

BatchLoader::GraphQL.for(object.id).batch(default_value: []) do |post_ids, loader|
  Image.where(post_id: post_ids).each { |i| loader.call(i.post_id, i) }
end
需要 登录 后方可回复, 如果你还没有账号请 注册新账号