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
(我在这里吐槽,因为还没有提供实际的实现)
我在这个 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
(我在这里吐槽,因为还没有提供实际的实现)