Files
talk/plugins/talk-plugin-deep-reply-count/index.js
T
2018-01-11 20:00:34 -07:00

94 lines
2.4 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);
},
},
},
};