diff --git a/public/openapi/components/schemas/TopicObject.yaml b/public/openapi/components/schemas/TopicObject.yaml index 9481d81305..69662e0080 100644 --- a/public/openapi/components/schemas/TopicObject.yaml +++ b/public/openapi/components/schemas/TopicObject.yaml @@ -26,6 +26,8 @@ TopicObject: type: number viewcount: type: number + postercount: + type: number teaserPid: oneOf: - type: number diff --git a/public/openapi/read/topic/tid/id.yaml b/public/openapi/read/topic/tid/id.yaml index 4c83350b37..cdc638a1f5 100644 --- a/public/openapi/read/topic/tid/id.yaml +++ b/public/openapi/read/topic/tid/id.yaml @@ -36,6 +36,8 @@ get: type: number lastposttime: type: number + postercount: + type: number postcount: type: number viewcount: diff --git a/public/openapi/read/topic/topic_id/slug/post_index.yaml b/public/openapi/read/topic/topic_id/slug/post_index.yaml index 6d520ba1c1..d9374eff97 100644 --- a/public/openapi/read/topic/topic_id/slug/post_index.yaml +++ b/public/openapi/read/topic/topic_id/slug/post_index.yaml @@ -53,7 +53,7 @@ get: type: number viewcount: type: number - posterCount: + postercount: type: number description: The number of unique users who made a post in this topic mainPid: diff --git a/src/topics/data.js b/src/topics/data.js index 6b73163b4c..06476755ef 100644 --- a/src/topics/data.js +++ b/src/topics/data.js @@ -10,7 +10,7 @@ const plugins = require('../plugins'); const intFields = [ 'tid', 'cid', 'uid', 'mainPid', 'postcount', - 'viewcount', 'deleted', 'locked', 'pinned', + 'viewcount', 'postercount', 'deleted', 'locked', 'pinned', 'timestamp', 'upvotes', 'downvotes', 'lastposttime', 'deleterUid', ]; diff --git a/src/topics/index.js b/src/topics/index.js index 3ed54ce0e8..418797a3f7 100644 --- a/src/topics/index.js +++ b/src/topics/index.js @@ -146,7 +146,6 @@ Topics.getTopicWithPosts = async function (topicData, set, uid, start, stop, rev deleter, merger, related, - posterCount, ] = await Promise.all([ getMainPostAndReplies(topicData, set, uid, start, stop, reverse), categories.getCategoryData(topicData.cid), @@ -158,7 +157,6 @@ Topics.getTopicWithPosts = async function (topicData, set, uid, start, stop, rev getDeleter(topicData), getMerger(topicData), getRelated(topicData, uid), - db.sortedSetCard('tid:' + topicData.tid + ':posters'), ]); topicData.posts = posts; @@ -181,7 +179,6 @@ Topics.getTopicWithPosts = async function (topicData, set, uid, start, stop, rev topicData.mergedTimestampISO = utils.toISOString(topicData.mergedTimestamp); } topicData.related = related || []; - topicData.posterCount = posterCount; topicData.unreplied = topicData.postcount === 1; topicData.icons = []; diff --git a/src/topics/posts.js b/src/topics/posts.js index 7ecbf1fb86..883d66907f 100644 --- a/src/topics/posts.js +++ b/src/topics/posts.js @@ -174,6 +174,8 @@ module.exports = function (Topics) { } await Topics.increasePostCount(tid); await db.sortedSetIncrBy('tid:' + tid + ':posters', 1, postData.uid); + const posterCount = await db.sortedSetCard('tid:' + tid + ':posters'); + await Topics.setTopicField(tid, 'postercount', posterCount); await Topics.updateTeaser(tid); }; @@ -184,6 +186,9 @@ module.exports = function (Topics) { ], postData.pid); await Topics.decreasePostCount(tid); await db.sortedSetIncrBy('tid:' + tid + ':posters', -1, postData.uid); + await db.sortedSetsRemoveRangeByScore(['tid:' + tid + ':posters'], '-inf', 0); + const posterCount = await db.sortedSetCard('tid:' + tid + ':posters'); + await Topics.setTopicField(tid, 'postercount', posterCount); await Topics.updateTeaser(tid); }; diff --git a/src/upgrades/1.15.0/topic_poster_count.js b/src/upgrades/1.15.0/topic_poster_count.js new file mode 100644 index 0000000000..b07111c800 --- /dev/null +++ b/src/upgrades/1.15.0/topic_poster_count.js @@ -0,0 +1,29 @@ +'use strict'; + +const db = require('../../database'); + +const batch = require('../../batch'); + +module.exports = { + name: 'Store poster count in topic hash', + timestamp: Date.UTC(2020, 9, 24), + method: async function () { + const progress = this.progress; + + await batch.processSortedSet('topics:tid', async function (tids) { + progress.incr(tids.length); + const keys = tids.map(tid => 'tid:' + tid + ':posters'); + await db.sortedSetsRemoveRangeByScore(keys, '-inf', 0); + const counts = await db.sortedSetsCard(keys); + for (let i = 0; i < tids.length; i++) { + if (counts[i] > 0) { + // eslint-disable-next-line no-await-in-loop + await db.setObjectField('topic:' + tids[i], 'postercount', counts[i]); + } + } + }, { + progress: progress, + batchSize: 500, + }); + }, +};