Files
talk/plugins/talk-plugin-deep-reply-count/index.js
T
2017-09-14 13:08:01 -06:00

82 lines
2.3 KiB
JavaScript

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);
}
}
}
};