const _ = require('lodash'); const DataLoader = require('dataloader'); const CommentModel = require('../../models/comment'); console.warn('Enabling the talk-plugin-deep-reply-count plugin introduces a signifigant performance impact on larger sites, use with care.'); // genDeepCommentCount will return the deep comment count for a given parent id. const genDeepCommentCount = async (context, parent_ids) => { // Get all the replies to the parent comments. const replies = await CommentModel .find({ parent_id: { $in: _.uniq(parent_ids), }, }, { id: 1, reply_count: 1, parent_id: 1, }); // Get all the replies that have comments on them. const commentedOnReplies = replies.filter(({reply_count}) => { return reply_count && reply_count > 0; }); let deepReplyCount = []; // And if there were any.. if (commentedOnReplies.length > 0) { // Load the reply count for each of them. deepReplyCount = await context.loaders.Comments.getDeepCount.loadMany(_.uniq(commentedOnReplies.map(({id}) => { return id; }))); } // Get all the direct replies to the parent comments. const allDirectReplies = _.groupBy(replies, 'parent_id'); // Collect all the ancestor replies. const allAncestorReplies = _.groupBy(_.zip(commentedOnReplies, deepReplyCount), ([{parent_id}]) => { return parent_id; }); // Return the replies in an array matching that of the input parent_ids array. return parent_ids.map((parent_id) => { // Get the direct replies to this comment. const directReplies = parent_id in allDirectReplies ? allDirectReplies[parent_id] : []; const ancestorReplies = parent_id in allAncestorReplies ? allAncestorReplies[parent_id] : []; // Reduce this array. return ancestorReplies.reduce((acc, [, count]) => { return acc + count; }, directReplies.length); }); }; module.exports = { typeDefs: ` type Comment { # deepReplyCount is the count of all decendant replies. deepReplyCount: Int } `, loaders: (context) => ({ Comments: { getDeepCount: new DataLoader((parent_ids) => genDeepCommentCount(context, parent_ids)), } }), resolvers: { Comment: { deepReplyCount({id}, args, {loaders: {Comments}}) { return Comments.getDeepCount.load(id); } } } };