Challenge 1: Batch the Post.comments Resolver — Possible Solution ==================================================================== function createCommentsByPostLoader() { return new DataLoader(async (postIds) => { const allComments = await db.comments.findByPostIds(postIds); // ONE query // Group the flat result into one array PER postId, in the same // order as the input postIds array. return postIds.map((postId) => allComments.filter((comment) => comment.postId === postId) ); }); } // Resolver Post: { comments: (parent, args, context) => context.commentsByPostLoader.load(parent.id), } WHY THIS WORKS -------------- - The batch function receives postIds (an array of every post ID requested across all the .load() calls queued in one tick) and makes exactly ONE call to db.comments.findByPostIds(postIds) — this is the batching mechanism from the chapter, just applied to a one-to-MANY relationship instead of the chapter's one-to-ONE User lookup example. - The key difference from the chapter's userLoader example: each postId doesn't map to a single comment, it maps to an ARRAY of comments. The return value must still be one entry per input postId, in the same order — but here each entry is itself an array (built with .filter()) rather than a single found object (built with .find(), as the chapter's user loader did). - Using .filter() instead of .find() is the key adaptation: for each postId, we filter allComments down to just the ones belonging to that post — if a post has zero comments, .filter() naturally returns an empty array for it, which is the correct "no comments" result rather than undefined or null. - Just like the chapter's example, the loader is read from context (context.commentsByPostLoader), meaning it must be created fresh per request alongside the userLoader from the chapter — never as a shared global instance, for exactly the reasons the chapter's tip box warns about.