Skip to content

Instantly share code, notes, and snippets.

@gleuch
Last active December 2, 2022 04:11
Show Gist options
  • Save gleuch/ac40a4cb6bc103bec75c1fc3a769bc69 to your computer and use it in GitHub Desktop.
Save gleuch/ac40a4cb6bc103bec75c1fc3a769bc69 to your computer and use it in GitHub Desktop.
Prisma find in batches extension

findInBatches extension for Prisma

Prisma client extension function to find many results in batches.

NOTE: Requires Prisma 4.7.0 or later with previewFeatures = ["clientExtensions"] in schema.prisma. https://www.prisma.io/docs/concepts/components/prisma-client/client-extensions

Usage

client.MODEL_NAME.findInBatches({ maxPages: Infinity, take: 1000, ...query }, callbackFn);

Examples

// Find all users in batches with @gmail.com email
client.user.findInBatches({ where: { email: { endsWith: '@gmail.com' } } }, async (results, page) => {
  // Do something with results
});

// Find first 2000 users names and email addresses in batches of 100 skipping the first 500 users
client.user.findInBatches(
  { maxPages: 20, skip: 500, take: 100, select: { name: true, email: true } },
  async (results, page) => {
    // Do something with results
  },
);
// Initialize Prisma client
let client = new PrismaClient();
// Extend client model
client = client.$extends({
model: {
$allModels: {
/**
* Prisma find in batches query
* @function
* @param args {object} - Prisma query arguments
* @param args.maxPages {integer} - Maximum page interations to make. _(default: Infinity)_
* @param args.skip {integer} - Initial offset. _(default: 0)_
* @param args.take {integer} - Number of items to take (limit) per batch. _(default: 1000)_
* @param callback {function} - Callback function to process results. Receives two arguments: `results` and `page`.
* @return {object}
*/
async findInBatches(args, callback) {
// Allow passing only callback function _(not recommended)_
if (!callback && typeof args === 'function') {
callback = args;
args = {};
}
// Ensure callback function exists
if (typeof callback !== 'function') {
throw new Error('A callback function is required');
}
// Set max pages, skip offset, and take amount per batch
const { maxPages = Infinity, skip = 0, take = 1000, ...queryArgs } = args;
// Iterate through batches
let count = 0;
let pages = 0;
while (maxPages > pages) {
// Query model
const results = await this.findMany({ ...queryArgs, take, skip: (take * pages) + skip });
// Pass results to callback function
await callback(results, pages);
// Increment pages and counts
count += results.length;
pages += 1;
// Halt if no more results
if (take > results.length) {
break;
}
}
return { count, pages };
},
},
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment