通过在graphql中避免N + 1查询来获取user_profiles

时间:2019-08-22 08:04:19

标签: ruby-on-rails ruby ruby-on-rails-5

我正在使用graphiql-ruby gem来使用graphql。我正在尝试获取具有其用户资料和公司的用户列表。但是,它消耗了5分钟以上的时间,并多次击中了api。它甚至使我的服务器崩溃。有人可以帮我吗?

这就是我所做的

module Queries
  module Users
    extend ActiveSupport::Concern
    include GraphQL::Schema::Member::GraphQLTypeNames

    included do
      field :users, [Types::UserType], null: false
      field :user, Types::UserType, null: false do
        argument :id, ID, required: true
      end
      field :currentUser, Types::UserType, null: false
    end

    # Get all users list except admins
    def users
      User.where.not(roles: ['admin'])
      # context[:current_user].logs.info!('User Data Fetched') && user
    end

    def user(id:)
      User.find(id)
    end

    def current_user
      context[:current_user]
    end
  end
end


module Types
  class UserType < Types::BaseObject
    field :id, ID, null: false
    field :email, String, null: false
    field :user_profile, Types::UserProfileType, null: false
    field :grants, [Types::GrantType], null: true
    field :companies, [Types::CompanyType], null: true
    field :my_companies_with_grants, [Types::CompanyGrantType], null: true

    def grants
      Grant.where(user_id: object.id)
    end

    def my_companies_with_grants
      current_user = User.find_by(id: object.id)
      company = current_user.companies
      userid = current_user.id
      company.map {|comp| { company: comp, grants: comp.get_user_grants(userid), company_id: comp.id } }
    end
  end
end

这是我查询用户列表的方式

query {
    employees: users {
      id
      email
      userProfile {
        ...UserProfile
      }
      roles
      createdAt
      companies {
        ...Company
      }
      grants {
        ...Grant
      }
    }
  }
  ${COMPANY}
  ${GRANT}
  ${USER_PROFILE}

为什么加载所有用户的时间太长?如何提高效率?

更新

class ApiSchema < GraphQL::Schema
  mutation(Types::MutationType)
  query(Types::QueryType)

  use GraphQL::Batch
end

记录加载器

class RecordLoader < GraphQL::Batch::Loader
  def initialize(model)
    @model = model
  end

  def perform(ids)
    @model.where(id: ids).each { |record| fulfill(record.id, record) }
    ids.each { |id| fulfill(id, nil) unless fulfilled?(id) }
  end
end

我更改了user_type.rb,并对user_profile进行了以下操作

 field :user_profile, [Types::UserProfileType, null: true], null: false do
      argument :id, [ID], required: true
 end



 def user_profile(ids:)
      RecordLoader.for(UserProfile).load_many(ids)
  end

但是我遇到"message":"Field 'userProfile' is missing required arguments: ids"问题

我设置了graphql-batch,但无法确定我应该在哪里使用RecordLoader(类型和解析器)

0 个答案:

没有答案