feat: cache tags:topic:count

v1.18.x
Barış Soner Uşaklı 6 years ago
parent 1789ecb45c
commit 63bd252fba

@ -1,16 +1,17 @@
'use strict'; 'use strict';
var async = require('async'); const async = require('async');
var validator = require('validator'); const validator = require('validator');
const _ = require('lodash');
var _ = require('lodash');
var db = require('../database'); const db = require('../database');
var meta = require('../meta'); const meta = require('../meta');
var categories = require('../categories'); const categories = require('../categories');
var plugins = require('../plugins'); const plugins = require('../plugins');
var utils = require('../utils'); const utils = require('../utils');
var batch = require('../batch'); const batch = require('../batch');
const cache = require('../cache');
module.exports = function (Topics) { module.exports = function (Topics) {
Topics.createTags = async function (tags, tid, timestamp) { Topics.createTags = async function (tags, tid, timestamp) {
@ -53,6 +54,7 @@ module.exports = function (Topics) {
const isMember = await db.isSortedSetMember('tags:topic:count', tag); const isMember = await db.isSortedSetMember('tags:topic:count', tag);
if (!isMember) { if (!isMember) {
await db.sortedSetAdd('tags:topic:count', 0, tag); await db.sortedSetAdd('tags:topic:count', 0, tag);
cache.del('tags:topic:count');
} }
}; };
@ -91,6 +93,7 @@ module.exports = function (Topics) {
async function updateTagCount(tag) { async function updateTagCount(tag) {
const count = await Topics.getTagTopicCount(tag); const count = await Topics.getTagTopicCount(tag);
await db.sortedSetAdd('tags:topic:count', count || 0, tag); await db.sortedSetAdd('tags:topic:count', count || 0, tag);
cache.del('tags:topic:count');
} }
Topics.getTagTids = async function (tag, start, stop) { Topics.getTagTids = async function (tag, start, stop) {
@ -109,6 +112,7 @@ module.exports = function (Topics) {
const keys = tags.map(tag => 'tag:' + tag + ':topics'); const keys = tags.map(tag => 'tag:' + tag + ':topics');
await db.deleteAll(keys); await db.deleteAll(keys);
await db.sortedSetRemove('tags:topic:count', tags); await db.sortedSetRemove('tags:topic:count', tags);
cache.del('tags:topic:count');
await db.deleteAll(tags.map(tag => 'tag:' + tag)); await db.deleteAll(tags.map(tag => 'tag:' + tag));
}; };
@ -166,7 +170,7 @@ module.exports = function (Topics) {
const topicTags = await Topics.getTopicsTags(tids); const topicTags = await Topics.getTopicsTags(tids);
const uniqueTopicTags = _.uniq(_.flatten(topicTags)); const uniqueTopicTags = _.uniq(_.flatten(topicTags));
var tags = uniqueTopicTags.map(tag => ({ value: tag })); const tags = uniqueTopicTags.map(tag => ({ value: tag }));
const [tagData, counts] = await Promise.all([ const [tagData, counts] = await Promise.all([
Topics.getTagData(tags), Topics.getTagData(tags),
@ -177,7 +181,7 @@ module.exports = function (Topics) {
tag.score = counts[index] ? counts[index] : 0; tag.score = counts[index] ? counts[index] : 0;
}); });
var tagDataMap = _.zipObject(uniqueTopicTags, tagData); const tagDataMap = _.zipObject(uniqueTopicTags, tagData);
topicTags.forEach(function (tags, index) { topicTags.forEach(function (tags, index) {
if (Array.isArray(tags)) { if (Array.isArray(tags)) {
@ -230,6 +234,14 @@ module.exports = function (Topics) {
return result.matches; return result.matches;
}; };
async function getAllTags() {
const cached = cache.get('tags:topic:count');
if (cached !== undefined) {
return cached;
}
return await db.getSortedSetRevRange('tags:topic:count', 0, -1);
}
async function findMatches(query, cid) { async function findMatches(query, cid) {
let tagWhitelist = []; let tagWhitelist = [];
if (parseInt(cid, 10)) { if (parseInt(cid, 10)) {
@ -239,13 +251,13 @@ module.exports = function (Topics) {
if (Array.isArray(tagWhitelist[0]) && tagWhitelist[0].length) { if (Array.isArray(tagWhitelist[0]) && tagWhitelist[0].length) {
tags = tagWhitelist[0]; tags = tagWhitelist[0];
} else { } else {
tags = await db.getSortedSetRevRange('tags:topic:count', 0, -1); tags = await getAllTags();
} }
query = query.toLowerCase(); query = query.toLowerCase();
var matches = []; const matches = [];
for (var i = 0; i < tags.length; i += 1) { for (let i = 0; i < tags.length; i += 1) {
if (tags[i].toLowerCase().startsWith(query)) { if (tags[i].toLowerCase().startsWith(query)) {
matches.push(tags[i]); matches.push(tags[i]);
if (matches.length > 19) { if (matches.length > 19) {
@ -259,7 +271,7 @@ module.exports = function (Topics) {
} }
Topics.searchAndLoadTags = async function (data) { Topics.searchAndLoadTags = async function (data) {
var searchResult = { const searchResult = {
tags: [], tags: [],
matchCount: 0, matchCount: 0,
pageCount: 1, pageCount: 1,
@ -288,15 +300,13 @@ module.exports = function (Topics) {
return await plugins.fireHook('filter:topic.getRelatedTopics', { topic: topicData, uid: uid }); return await plugins.fireHook('filter:topic.getRelatedTopics', { topic: topicData, uid: uid });
} }
var maximumTopics = meta.config.maximumRelatedTopics; let maximumTopics = meta.config.maximumRelatedTopics;
if (maximumTopics === 0 || !topicData.tags || !topicData.tags.length) { if (maximumTopics === 0 || !topicData.tags || !topicData.tags.length) {
return []; return [];
} }
maximumTopics = maximumTopics || 5; maximumTopics = maximumTopics || 5;
let tids = await async.map(topicData.tags, async function (tag) { let tids = await Promise.all(topicData.tags.map(tag => Topics.getTagTids(tag.value, 0, 5)));
return await Topics.getTagTids(tag.value, 0, 5);
});
tids = _.shuffle(_.uniq(_.flatten(tids))).slice(0, maximumTopics); tids = _.shuffle(_.uniq(_.flatten(tids))).slice(0, maximumTopics);
const topics = await Topics.getTopics(tids, uid); const topics = await Topics.getTopics(tids, uid);
return topics.filter(t => t && !t.deleted && parseInt(t.uid, 10) !== parseInt(uid, 10)); return topics.filter(t => t && !t.deleted && parseInt(t.uid, 10) !== parseInt(uid, 10));

Loading…
Cancel
Save