【问题标题】:Graphql Ruby N + 1 Queries because of method calling another relationship由于方法调用另一个关系,Graphql Ruby N + 1 查询
【发布时间】:2021-06-08 11:39:22
【问题描述】:

我正在使用 graphql 和批处理加载器 gem 并遇到这个 N+1 查询:

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

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
  }
}

【问题讨论】:

    标签: ruby-on-rails graphql lazy-loading graphql-ruby


    【解决方案1】:

    假设您使用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
    

    (由于尚未提供实际实现,我在这里吐口水)

    【讨论】:

    • 要去看看,但我用的是graphql gem,但它在域名graphql-ruby下所以不确定它们是否相同
    • 当我之前查看前瞻时,一堆网络崩溃了!
    • highfive.png,这里也一样 :)
    • 我认为是一样的,graphql-ruby.orggem install graphql(从未检查过,但我认为没有其他人为 ruby​​ 实现了整个 gql,所以它现在是一种标准)
    • 太棒了,感谢分享宝石 - 看起来很有用!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多