feat: ability to search categories, #8813
parent
faeb637353
commit
34c42c6fa3
@ -0,0 +1,71 @@
|
||||
'use strict';
|
||||
|
||||
const _ = require('lodash');
|
||||
|
||||
const privileges = require('../privileges');
|
||||
const plugins = require('../plugins');
|
||||
const db = require('../database');
|
||||
|
||||
module.exports = function (Categories) {
|
||||
Categories.search = async function (data) {
|
||||
const query = data.query || '';
|
||||
const page = data.page || 1;
|
||||
const uid = data.uid || 0;
|
||||
const paginate = data.hasOwnProperty('paginate') ? data.paginate : true;
|
||||
|
||||
const startTime = process.hrtime();
|
||||
|
||||
let cids = await findCids(query, data.hardCap);
|
||||
|
||||
const result = await plugins.hooks.fire('filter:categories.search', {
|
||||
cids: cids,
|
||||
uid: uid,
|
||||
});
|
||||
cids = await privileges.categories.filterCids('find', result.cids, uid);
|
||||
|
||||
const searchResult = {
|
||||
matchCount: cids.length,
|
||||
};
|
||||
|
||||
if (paginate) {
|
||||
const resultsPerPage = data.resultsPerPage || 50;
|
||||
const start = Math.max(0, page - 1) * resultsPerPage;
|
||||
const stop = start + resultsPerPage;
|
||||
searchResult.pageCount = Math.ceil(cids.length / resultsPerPage);
|
||||
cids = cids.slice(start, stop);
|
||||
}
|
||||
|
||||
const childrenCids = await getChildrenCids(cids, uid);
|
||||
const uniqCids = _.uniq(cids.concat(childrenCids));
|
||||
const categoryData = await Categories.getCategories(uniqCids, uid);
|
||||
|
||||
Categories.getTree(categoryData, 0);
|
||||
await Categories.getRecentTopicReplies(categoryData, uid, data.qs);
|
||||
categoryData.sort(function (c1, c2) {
|
||||
if (c1.parentCid !== c2.parentCid) {
|
||||
return c1.parentCid - c2.parentCid;
|
||||
}
|
||||
return c1.order - c2.order;
|
||||
});
|
||||
searchResult.timing = (process.elapsedTimeSince(startTime) / 1000).toFixed(2);
|
||||
searchResult.categories = categoryData.filter(c => cids.includes(c.cid));
|
||||
return searchResult;
|
||||
};
|
||||
|
||||
async function findCids(query, hardCap) {
|
||||
if (!query || String(query).length < 2) {
|
||||
return [];
|
||||
}
|
||||
const data = await db.getSortedSetScan({
|
||||
key: 'categories:name',
|
||||
match: '*' + String(query).toLowerCase() + '*',
|
||||
limit: hardCap || 500,
|
||||
});
|
||||
return data.map(data => parseInt(data.split(':').pop(), 10));
|
||||
}
|
||||
|
||||
async function getChildrenCids(cids, uid) {
|
||||
const childrenCids = await Promise.all(cids.map(cid => Categories.getChildrenCids(cid)));
|
||||
return await privileges.categories.filterCids('find', childrenCids.flat(), uid);
|
||||
}
|
||||
};
|
@ -0,0 +1,30 @@
|
||||
'use strict';
|
||||
|
||||
const db = require('../../database');
|
||||
const batch = require('../../batch');
|
||||
|
||||
module.exports = {
|
||||
name: 'Create category name sorted set',
|
||||
timestamp: Date.UTC(2021, 0, 27),
|
||||
method: async function () {
|
||||
const progress = this.progress;
|
||||
|
||||
await batch.processSortedSet('categories:cid', async function (cids) {
|
||||
const keys = cids.map(cid => 'category:' + cid);
|
||||
let categoryData = await db.getObjectsFields(keys, ['cid', 'name']);
|
||||
categoryData = categoryData.filter(c => c.cid && c.name);
|
||||
const bulkAdd = categoryData.map(function (cat) {
|
||||
return [
|
||||
'categories:name',
|
||||
0,
|
||||
String(cat.name).substr(0, 200).toLowerCase() + ':' + cat.cid,
|
||||
];
|
||||
});
|
||||
await db.sortedSetAddBulk(bulkAdd);
|
||||
progress.incr(cids.length);
|
||||
}, {
|
||||
batch: 500,
|
||||
progress: progress,
|
||||
});
|
||||
},
|
||||
};
|
Loading…
Reference in New Issue