Skip to content

Optimize database SQL queries using GraphQL::Execution::Lookahead  #152

@sergeyantonov1

Description

@sergeyantonov1

What is lookahead?
https://graphql-ruby.org/queries/lookahead.html#getting-a-lookahead

How we can implement it?
In the example below recent_assessments association will be loaded if can_make_assessment will be selected in GraphQL request.

# app/graphql/resolvers/base.rb
module Resolvers
  class Base < GraphQL::Schema::Resolver
    include ActionPolicy::GraphQL::Behaviour

    argument_class Types::BaseArgument

    def resolve(**options)
      @options = options
      fetch_data
    end

    private

    attr_reader :options

    def fetch_data
      raise NotImplementedError
    end

    def current_user
      @current_user ||= context[:current_user]
    end

    def preload_associations
      lookahead_selection_names.each_with_object([]) do |selection, associations|
        associations << self.class::PRELOAD_ASSOCIATIONS_MAPPING[selection]
      end.flatten.compact
    end

    def lookahead_selection_names
      options[:lookahead].selections.map { |s| s.name.to_sym }
    end
  end
end

# app/graphql/resolvers/users.rb
module Resolvers
  class Users < Resolvers::Base
    # some arguments

    extras [:lookahead]

    type [Types::UserType], null: true

    PRELOAD_ASSOCIATIONS_MAPPING = {
      can_make_assessment: [:recent_assessments]
    }.freeze

    def fetch_data
      sorted_relation(filtered_relation)
    end

    private

    def filtered_relation
      FilteredUsersQuery.new(relation, options).all
    end

    def relation
      object.users.includes(preload_associations)
    end
  end
end

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions