Skip to content

Instantly share code, notes, and snippets.

@rmosolgo
Created April 1, 2025 22:24
Show Gist options
  • Save rmosolgo/e52b021f1b693b1cae5a91fe4342641b to your computer and use it in GitHub Desktop.
Save rmosolgo/e52b021f1b693b1cae5a91fe4342641b to your computer and use it in GitHub Desktop.
Avoiding N+1 loads in different GraphQL subtrees
require "bundler/inline"
gemfile do
gem "graphql", "2.5.0"
gem "activerecord", require: "active_record"
gem "sqlite3"
gem "logger"
end
# Set up the database for the example
ActiveRecord::Base.establish_connection({ adapter: "sqlite3", database: ":memory:" })
ActiveRecord::Schema.define do
self.verbose = false
create_table :books do |t|
t.string :title
t.integer :author_id
end
create_table :authors do |t|
t.string :name
end
end
class Author < ActiveRecord::Base
has_many :books
end
class Book < ActiveRecord::Base
belongs_to :author
end
a1 = Author.create(name: "Beatrix Potter")
a1.books.create!(title: "The Tale of Ginger and Pickles")
a1.books.create!(title: "The Tale of Samuel Whiskers")
a2 = Author.create!(name: "Sandra Boynton")
a2.books.create!(title: "Birthday Monsters")
a2.books.create!(title: "But Not the Hippopotamus")
class MySchema < GraphQL::Schema
class Author < GraphQL::Schema::Object
field :name, String
end
class Book < GraphQL::Schema::Object
field :title, String
field :author, Author
if ENV["WITH_DATALOADER"]
def author
# Could also be:
# dataloader.with(GraphQL::Dataloader::ActiveRecordAssociationSource, :author).load(object)
dataload_association(:author)
end
end
end
class Query < GraphQL::Schema::Object
field :books, [Book] do
argument :ids, [ID]
end
def books(ids:)
::Book.where(id: ids)
end
end
query(Query)
use GraphQL::Dataloader
end
ActiveRecord::Base.logger = Logger.new(STDOUT)
pp MySchema.execute <<~GRAPHQL
query GetManyBooks {
books(ids: [1, 2, 3, 4]) {
title
author {
name
}
}
}
GRAPHQL
# ruby list_of_nodes_example.rb
# D, [2025-04-01T18:22:15.672155 #86219] DEBUG -- : Book Load (0.1ms) SELECT "books".* FROM "books" WHERE "books"."id" IN (?, ?, ?, ?) [["id", 1], ["id", 2], ["id", 3], ["id", 4]]
# D, [2025-04-01T18:22:15.673230 #86219] DEBUG -- : Author Load (0.1ms) SELECT "authors".* FROM "authors" WHERE "authors"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
# D, [2025-04-01T18:22:15.673620 #86219] DEBUG -- : Author Load (0.0ms) SELECT "authors".* FROM "authors" WHERE "authors"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
# D, [2025-04-01T18:22:15.673945 #86219] DEBUG -- : Author Load (0.0ms) SELECT "authors".* FROM "authors" WHERE "authors"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]
# D, [2025-04-01T18:22:15.674262 #86219] DEBUG -- : Author Load (0.0ms) SELECT "authors".* FROM "authors" WHERE "authors"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]
#
# WITH_DATALOADER=1 ruby list_of_nodes_example.rb
# D, [2025-04-01T18:22:23.088179 #86235] DEBUG -- : Book Load (0.2ms) SELECT "books".* FROM "books" WHERE "books"."id" IN (?, ?, ?, ?) [["id", 1], ["id", 2], ["id", 3], ["id", 4]]
# D, [2025-04-01T18:22:23.095555 #86235] DEBUG -- : Author Load (0.2ms) SELECT "authors".* FROM "authors" WHERE "authors"."id" IN (?, ?) [["id", 1], ["id", 2]]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment