这是 MEAN 项目的一部分。 在 UI 上,正在显示服务日志表(mat-table)。该表还具有 matSort 和 matPagination。 UI 有多个过滤器选项(mat-select)加上一个搜索输入字段来过滤从服务器接收的数据。为了从服务器获取数据,使用了下面的 Node 服务方法。它基本上是猫鼬 find() 查询的变体。请注意,以下代码中的“filtObj”是以角度创建的对象数组,用于定义用户选择的过滤器。代码中给出了示例。
对于测试设置,我在 ServiceLog 集合中只有 20 个文档。 只有 20 个文档,执行节点服务方法所需的时间约为 1.5 秒。在生产环境中,到年底,集合中的文档数量可能会达到 7,000 到 10,000。我担心在完全加载集合的情况下执行数据获取所需的时间。
请告知以下方法中的代码是否可以改进。
async function getServiceLog(filter, sortKey, sortOrder, pageSize, pageIndex, filtObj){
console.time('getServiceLog');
let fetchedDocs;
let docQuery;
////////////// example of a filtObj: [ { FY: '2020-21' }, { dueMonth: '2020-07' } ]
///////////// There are 9 filters in UI, some or all may be applied by the user.
///////////// If no filter is applied then filtObj = []
let filtType = 'none'; /// to indicate that user did not search for any text nor applied any filter
if(filter && filtObj.length <= 0) { /// user typed something in search input but no filters
filtType = 'filter'
} else if(!filter && filtObj.length > 0) { /// no Search input but One or more filters were applied
filtType = 'filtObj'
} else if(filter && filtObj.length > 0) { /// both of the above
filtType = 'both'
}
switch(filtType) {
case "none":
docQuery = ServiceLog.find().collation({ locale: 'en'});
break;
case "filter": /// searching only in compName and servNAme fields
docQuery = ServiceLog.find({
$or: [
{ compName: { $regex: filter, $options: 'i' } },
{ servName: { $regex: filter, $options: 'i' } },
],
}).collation({ locale: 'en'});
break;
case "filtObj":
docQuery = ServiceLog.find({
$and: filtObj
}).collation({ locale: 'en'});
break;
case "both":
docQuery = ServiceLog.find({
$and: [
{
$or: [
{ compName: { $regex: filter, $options: 'i' } },
{ servName: { $regex: filter, $options: 'i' } },
],
},
{
$and: filtObj
}
]
}).collation({ locale: 'en'});
break;
}
///// the below block is to find out the correct count of documents matching the search/filter criteria
fetchedDocs = await docQuery;
if(!fetchedDocs) fetchedDocs = [];
totalCount = fetchedDocs.length;
if(!totalCount) totalCount = 0;
/////// and after getting the filtered collection count I am modifying the query below
/////// to sort and apply pageIndex/pageSize of matPaginator
/////// so there are two query calls to the DB. Can the two calls be avoided?
if(pageSize && pageIndex >= 0) {
if(!sortKey) {
docQuery.skip(pageSize * pageIndex).limit(pageSize);
}else{
if(sortOrder === 'desc') {
sortOption = '-' + sortKey
}else {
sortOption = sortKey
}
docQuery.sort(sortOption).skip(pageSize * pageIndex).limit(pageSize);
}
}
fetchedDocs = await docQuery;
if(!fetchedDocs) fetchedDocs = [];
servLogFilts = await getServiceLogFilters(); // given below
servLogData = {
servicelogs: fetchedDocs,
totalCount: totalCount,
servLogFilts: servLogFilts
}
console.timeEnd('getServiceLog');
return servLogData;
}
///////////// END OF getServiceLog function
//// the below function generates the array of options for each filter in the UI
//// this is causing multiple calls to the collection. How to improve this?
async function getServiceLogFilters() {
arrFY = await ServiceLog.distinct('FY');
if(!arrFY) {
arrFY = [];
} else {
arrFY.sort();
arrFY.reverse();
}
arrCalYear = await ServiceLog.distinct('calYear');
if(!arrCalYear) {
arrCalYear = [];
} else {
arrCalYear.sort();
arrCalYear.reverse();
}
arrCalMonth = await ServiceLog.distinct('calMonth');
if(!arrCalMonth) {
arrCalMonth = [];
} else {
arrCalMonth.sort();
arrCalMonth.reverse();
}
arrDueMonth = await ServiceLog.distinct('dueMonth');
if(!arrDueMonth) {
arrDueMonth = [];
} else {
arrDueMonth.sort();
arrDueMonth.reverse();
}
arrCompCat = await ServiceLog.distinct('compCat');
if(!arrCompCat) {
arrCompCat = [];
} else {
if(arrCompCat.length = 1 && arrCompCat[0] === '') {
arrCompCat = [];
} else {
arrCompCat.sort();
}
}
arrServStatus = await ServiceLog.distinct('servStatus');
if(!arrServStatus) {
arrServStatus = [];
} else {
arrServStatus.sort();
}
arrServCat = await ServiceLog.distinct('servCat');
if(!arrServCat) {
arrServCat = [];
} else {
arrServCat.sort();
}
arrExecName = await ServiceLog.distinct('execName');
if(!arrExecName) {
arrExecName = [];
} else {
arrExecName.sort();
}
arrPaytStatus = await ServiceLog.distinct('paytStatus');
if(!arrPaytStatus) {
arrPaytStatus = [];
} else {
arrPaytStatus.sort();
}
const servLogFilts = {
arrFY: arrFY,
arrCalYear: arrCalYear,
arrCalMonth: arrCalMonth,
arrDueMonth: arrDueMonth,
arrCompCat: arrCompCat,
arrServStatus: arrServStatus,
arrServCat: arrServCat,
arrExecName: arrExecName,
arrPaytStatus: arrPaytStatus
}
return servLogFilts;
}