DataLoaders (https://github.com/graphql/dataloader) are useful in solving the n+1 problem so often encountered whilst building GraphQL APIs. DataLoaders act as a query batching and caching solution.
A good example to start with is imports/plugins/core/core/server/no-meteor/queries.js. There we have shopById query used in a resolver for a product variant. shopById issues a query to Mongo context.collections.Shops.findOne({ _id }). On a product listing page shopById gets called with the same shopId for every product and product variant, which results in a significant number of queries to Mongo which can be avoided. The lookup itself is fast as this collection is indexed. However we still have an unnecessary number of roundtrips to the DB.
Another example isimports/plugins/included/simple-inventory/server/no-meteor/utils/inventoryForProductConfigurations.js. The call to fetch inventory information SimpleInventory.find(...) would benefit from batching if there was a DataLoader in place.
A proposed architecture would allow each plugin to register their own DataLoaders map using functionsByType prop in the plugin's register.js. Each plugin would then provide a factory function to create DataLoaders, which will then be merged into context.dataLoaders and re-created on every request, as suggested here (https://github.com/graphql/dataloader#caching-per-request).
DataLoaders (https://github.com/graphql/dataloader) are useful in solving the n+1 problem so often encountered whilst building GraphQL APIs. DataLoaders act as a query batching and caching solution. A good example to start with is
imports/plugins/core/core/server/no-meteor/queries.js
. There we haveshopById
query used in a resolver for a product variant.shopById
issues a query to Mongocontext.collections.Shops.findOne({ _id })
. On a product listing pageshopById
gets called with the sameshopId
for every product and product variant, which results in a significant number of queries to Mongo which can be avoided. The lookup itself is fast as this collection is indexed. However we still have an unnecessary number of roundtrips to the DB. Another example isimports/plugins/included/simple-inventory/server/no-meteor/utils/inventoryForProductConfigurations.js
. The call to fetch inventory informationSimpleInventory.find(...)
would benefit from batching if there was a DataLoader in place.A proposed architecture would allow each plugin to register their own DataLoaders map using
functionsByType
prop in the plugin'sregister.js
. Each plugin would then provide a factory function to create DataLoaders, which will then be merged intocontext.dataLoaders
and re-created on every request, as suggested here (https://github.com/graphql/dataloader#caching-per-request).