您好,我公司开发的婚恋平台,由于业务需要使用了比较复杂的【lookup联表查询】,近期数据增多后,经常出现因查询超时失败的糟糕情况,不知道如何优化了!
如图,业务使用了两个表,一个是约会信息表meet,一个是用户信息表user,我们需要提供对用户信息、约会信息的筛选查询、排序功能,需要对两个表的信息进行联合复杂查询、排序。现在老是出错,不知道怎么优化了,求大神帮忙看看!
查询代码如下:
async function meet_list(event) {
var match = { sta: 1 };
var sort = { upT: -1 };
if (event.region_code.length == 1) {
match.zip0 = event.region_code[0] * 1;//同省
}
else if (event.region_code.length > 1) {
match.zip1 = event.region_code[1] * 1;//同城
}
if (event.sex > 0) {
match.sex = event.sex * 1;
}
if (event.edu >= 0) {
match.edu = event.edu * 1;
}
if (event.mar >= 0) {
match.mar = event.mar * 1;
}
if (event.more != '') {
switch (event.more) {
case 'sm':
match.sm = 1;
break;
case 'club':
let nowTs = Date.parse(new Date()) / 1000;
match.club = _.gt(nowTs);
break;
case 'vip':
match.vip = _.gt(100);
break;
case 'fn':
match.fn = _.gt(0);
break;
case 'face':
sort = { face: -1 };
break;
case 'ker':
sort = { ker: -1 };
break;
case 'kp':
sort = { kp: -1 };
break;
case 'hot':
sort = { post: -1 };
break;
case 'nx':
sort = { nx: -1 };
break;
case 'new':
sort = { _id: -1 };
break;
case 'xqx1':
match.sex = 1;
match.xqx = 1;
break;
case 'xqx2':
match.sex = 2;
match.xqx = 2;
break;
}
}
//年龄筛选
if (event.age.length > 1) {
match.birt = _.and(_.lte(event.age[0] * 1), _.gte(event.age[1] * 1));
}
var $ = db.command.aggregate
var commad = db.collection('meet').aggregate();
if (event.geo.length == 2) {
commad = commad.geoNear({
distanceField: 'distance', // 输出的每个记录中 distance 即是与给定点的距离
spherical: true,
distanceMultiplier: 6378137,//这样算出来的才是米
near: db.Geo.Point(event.geo[0], event.geo[1])
})
sort = { distance: 1, _id: -1 };
}
var res = await commad
.lookup({
from: 'user',
localField: '_openid',
foreignField: '_id',
as: 'user',
})
.replaceRoot({
newRoot: $.mergeObjects([$.arrayElemAt(['$user', 0]), '$$ROOT'])
})
.match(match)
.project({
name: 1,
sex: 1,
birt: 1,
club: 1,
sm: 1,
vip: 1,
face: 1,
edu: 1,
ker: 1,
kp: 1,
_id: 1,
_openid: 1,
type: 1,
tit: 1,
reg: 1,
ht: 1,
img: 1,
job: 1,
idea: 1,
post: 1,
upT: 1,
nx: 1,
cher: 1,
distance: 1
})
.sort(sort)
.skip(event.offset)
.limit(event.limit)
.end()
return res.list;
}
已参考这个进行了索引优化,但还是不行(可能是我对索引的理解不够透切)
https://developers.weixin.qq.com/community/minihome/article/doc/0008cc5e8cc2a8d5789a981bf55c13
相关配置,也已调成最大化
geoNear阶段之后,就match,再limit,这样之后lookup面对的数据量就只是limit条,而不是整个数据。
方法二:meet表中添加match需要的字段,不仅仅是openid;
方法三:就一个表meet,不需要lookup,用户信息完全放在meet中。