diff --git a/src/search.js b/src/search.js index db420c6ee5..978db18cc9 100644 --- a/src/search.js +++ b/src/search.js @@ -17,7 +17,7 @@ var search = module.exports; search.search = function (data, callback) { var start = process.hrtime(); data.searchIn = data.searchIn || 'titlesposts'; - + data.sortBy = data.sortBy || 'relevance'; async.waterfall([ function (next) { if (data.searchIn === 'posts' || data.searchIn === 'titles' || data.searchIn === 'titlesposts') { @@ -39,10 +39,14 @@ search.search = function (data, callback) { function searchInContent(data, callback) { data.uid = data.uid || 0; - var matchCount = 0; var pids; var metadata; var itemsPerPage = Math.min(data.itemsPerPage || 10, 100); + const returnData = { + posts: [], + matchCount: 0, + pageCount: 1, + }; async.waterfall([ function (next) { async.parallel({ @@ -72,8 +76,13 @@ function searchInContent(data, callback) { }, function (results, next) { pids = results.pids; + + if (data.returnIds) { + return callback(null, results); + } + if (!results.pids.length && !results.tids.length) { - return callback(null, { posts: [], matchCount: matchCount, pageCount: 1 }); + return callback(null, returnData); } topics.getMainPids(results.tids, next); @@ -93,28 +102,30 @@ function searchInContent(data, callback) { }, function (_metadata, next) { metadata = _metadata; - matchCount = metadata.pids.length; + returnData.matchCount = metadata.pids.length; + returnData.pageCount = Math.max(1, Math.ceil(parseInt(returnData.matchCount, 10) / itemsPerPage)); if (data.page) { - var start = Math.max(0, (data.page - 1)) * itemsPerPage; + const start = Math.max(0, (data.page - 1)) * itemsPerPage; metadata.pids = metadata.pids.slice(start, start + itemsPerPage); } posts.getPostSummaryByPids(metadata.pids, data.uid, {}, next); }, function (posts, next) { + returnData.posts = posts; // Append metadata to returned payload (without pids) delete metadata.pids; - next(null, Object.assign({ - posts: posts, - matchCount: matchCount, - pageCount: Math.max(1, Math.ceil(parseInt(matchCount, 10) / itemsPerPage)), - }, metadata)); + next(null, Object.assign(returnData, metadata)); }, ], callback); } function filterAndSort(pids, data, callback) { + if (data.sortBy === 'relevance' && !data.replies && !data.timeRange && !data.hasTags) { + return setImmediate(callback, null, pids); + } + async.waterfall([ function (next) { getMatchedPosts(pids, data, next); @@ -135,7 +146,6 @@ function filterAndSort(pids, data, callback) { }, function (result, next) { pids = result.posts.map(post => post && post.pid); - next(null, pids); }, ], callback); @@ -145,7 +155,7 @@ function getMatchedPosts(pids, data, callback) { var postFields = ['pid', 'uid', 'tid', 'timestamp', 'deleted', 'upvotes', 'downvotes']; var categoryFields = []; - if (data.sortBy && data.sortBy.startsWith('category.')) { + if (data.sortBy.startsWith('category.')) { categoryFields.push(data.sortBy.split('.')[1]); } @@ -161,7 +171,7 @@ function getMatchedPosts(pids, data, callback) { async.parallel({ users: function (next) { - if (data.sortBy && data.sortBy.startsWith('user')) { + if (data.sortBy.startsWith('user')) { uids = _.uniq(postsData.map(post => post.uid)); user.getUsersFields(uids, ['username'], next); } else { @@ -274,7 +284,7 @@ function filterByTags(posts, hasTags) { } function sortPosts(posts, data) { - if (!posts.length || !data.sortBy || data.sortBy === 'relevance') { + if (!posts.length || data.sortBy === 'relevance') { return; } @@ -322,14 +332,14 @@ function getSearchCids(data, callback) { if (data.categories.includes('watched')) { user.getWatchedCategories(data.uid, next); } else { - next(null, []); + setImmediate(next, null, []); } }, childrenCids: function (next) { if (data.searchChildren) { getChildrenCids(data.categories, data.uid, next); } else { - next(null, []); + setImmediate(next, null, []); } }, }, next); @@ -356,6 +366,6 @@ function getSearchUids(data, callback) { if (data.postedBy) { user.getUidsByUsernames(Array.isArray(data.postedBy) ? data.postedBy : [data.postedBy], callback); } else { - callback(null, []); + setImmediate(callback, null, []); } } diff --git a/src/topics/index.js b/src/topics/index.js index 005bb65b1e..f54dc9b325 100644 --- a/src/topics/index.js +++ b/src/topics/index.js @@ -289,10 +289,7 @@ Topics.getMainPids = function (tids, callback) { Topics.getTopicsFields(tids, ['mainPid'], next); }, function (topicData, next) { - var mainPids = topicData.map(function (topic) { - return topic && topic.mainPid; - }); - next(null, mainPids); + next(null, topicData.map(topic => topic && topic.mainPid)); }, ], callback); }; diff --git a/src/topics/suggested.js b/src/topics/suggested.js index c4c6d0dbea..3e8cd0e0c0 100644 --- a/src/topics/suggested.js +++ b/src/topics/suggested.js @@ -5,6 +5,7 @@ var async = require('async'); var _ = require('lodash'); const db = require('../database'); +const user = require('../user'); var privileges = require('../privileges'); var search = require('../search'); @@ -16,7 +17,7 @@ module.exports = function (Topics) { function (next) { async.parallel({ tagTids: function (next) { - getTidsWithSameTags(tid, uid, next); + getTidsWithSameTags(tid, next); }, searchTids: function (next) { getSearchTids(tid, uid, next); @@ -29,19 +30,26 @@ module.exports = function (Topics) { tids = _.shuffle(_.uniq(tids)); if (stop !== -1 && tids.length < stop - start + 1) { - getCategoryTids(tid, uid, next); + getCategoryTids(tid, next); } else { next(null, []); } }, function (categoryTids, next) { tids = _.uniq(tids.concat(categoryTids)).slice(start, stop !== -1 ? stop + 1 : undefined); + privileges.topics.filterTids('read', tids, uid, next); + }, + function (tids, next) { Topics.getTopicsByTids(tids, uid, next); }, + function (topics, next) { + topics = topics.filter(topic => topic && !topic.deleted && topic.tid !== tid); + user.blocks.filter(uid, topics, next); + }, ], callback); }; - function getTidsWithSameTags(tid, uid, callback) { + function getTidsWithSameTags(tid, callback) { async.waterfall([ function (next) { Topics.getTopicTags(tid, next); @@ -50,8 +58,7 @@ module.exports = function (Topics) { db.getSortedSetRevRange(tags.map(tag => 'tag:' + tag + ':topics'), 0, -1, next); }, function (tids, next) { - tids = _.uniq(tids).map(Number); - privileges.topics.filterTids('read', tids, uid, next); + next(null, _.uniq(tids).map(Number)); }, ], callback); } @@ -68,30 +75,25 @@ module.exports = function (Topics) { matchWords: 'any', categories: [topicData.cid], uid: uid, - page: 1, - itemsPerPage: 20, + returnIds: true, }, next); }, function (data, next) { - var tids = data.posts.map(post => post && post.tid); - next(null, tids); + next(null, _.shuffle(data.tids).slice(0, 20).map(Number)); }, ], callback); } - function getCategoryTids(tid, uid, callback) { + function getCategoryTids(tid, callback) { async.waterfall([ function (next) { Topics.getTopicField(tid, 'cid', next); }, function (cid, next) { - Topics.getRecentTopics(cid, uid, 0, 9, '', next); + db.getSortedSetRevRange('cid:' + cid + ':tids:lastposttime', 0, 9, next); }, - function (data, next) { - var tids = data.topics.filter(function (topic) { - return topic && !topic.deleted && tid !== topic.tid; - }).map(topic => topic && topic.tid); - next(null, tids); + function (tids, next) { + next(null, tids.map(Number)); }, ], callback); }