Graphql Ruby N + 1 查询因为调用另一个关系的方法

Graphql Ruby N + 1 Queries because of method calling another relationship

我在这个 N+1 查询中使用 graphql 和 batch-loader gem 和 运行:

我有一个属于帐户的日历约会,当我们显示约会时间时,我们将其基于帐户的时区。

def appointment_time
  read_attribute(:appointment_time).in_time_zone(self.account.timezone)
end
calendarAppts {
  appointmentTime
}

N+1 查询结果

POST /graphql
USE eager loading detected
  CalendarAppt => [:account]
  Add to your query: .includes([:account])
Call stack
  /....rb:866:in `appointment_time'
  /.../app/controllers/graphql_controller.rb:17:in `execute'

我还有许多其他实例方法创建 N+1 查询的类似示例,但不确定解决此问题的最佳方法。

到目前为止,我只是看到了直接征服急切加载关联的方法。我是否需要将每个这样的方法都视为一个关联?

例如,这就是我自己急切加载帐户的方式,当我调用此方法时是否也需要做类似的事情?

    field :account,
          AccountType,
          null: true,
          resolve: lambda { |obj, _args, _ctx|
            BatchLoader::GraphQL.for(obj.account_id).batch do |account_ids, loader|
              Account.where(id: account_ids).each { |account| loader.call(account.id, account) }
            end
          }

此外,如果我们这样做,它会调用帐户两次吗?

calendarAppts {
  appointmentTime
  account {
    id
    name
  }
}

假设您使用 graphql-ruby 来处理您的查询,您应该使用 lookahead 来查看需要哪些子字段并相应地准备您的查询。

因此,在您的情况下,在实现 callendarAppts 的方法中,您应该执行如下操作:

field :calendar_appts, ..., extras: [:lookahead]
def callendar_appts(lookadead:)
  scope = Model.where(...)
  if(lookahead.selects?(:appointment_time))
     scope = scope.includes([:accounts])
  end
  scope.all
end

(我在这里吐槽,因为还没有提供实际的实现)