背景:
之前不会用聚合,因此把数据库结构分为了用户表、帖子表、喜欢表。
小程序端请求一次列表,要根据帖子列表,循环查询用户表,并且还要做一系列的逻辑运算处理,计算当前帖子的权限、是否喜欢过、喜欢人数、是否有这个帖子管理权限等信息。
这样做有很多弊端:
- 处理速度慢,资源耗费严重,循环查询肯定慢且耗费资源,一个列表需要21次查询。
- 需要写大量逻辑处理代码,如计算管理权限,喜欢数量、当前用户是否喜欢,格式处理等等。
于是使用聚合进行了优化:
- 跨表查询
- 数据格式化
- 逻辑计算,权限判断、是否喜欢等
- 数据统计,喜欢总人数
- 权限判断,是否为管理员
- 限制输出
效果:
之前:上百行代码,多次查询,需要单独判断函数,处理时间在3000ms以上
之后:几行代码,一次查询,直接查询时算出结果,处理时间在300ms以内
数据库结构
代码实现:
const { OPENID } = cloud.getWXContext(context)
//构建查询条件
let query = null
switch (Number(event.listType)) {
case 0:
query = db.collection('post').aggregate()
.match({
//0我的
'_openid': OPENID
})
.sort({
createTime: -1
})
.skip(20 * (event.pageNum - 1))
.limit(20)
break;
case 1:
//1 随机
query = db.collection('post').aggregate()
.match({
public: true,
// feeling: _.gte(50)
})
.sample({
size: 20
})
break;
case 2:
query = db.collection('post').aggregate()
.match({
//2喜欢
likes: _.all([OPENID])
})
.sort({
createTime: -1
})
.skip(20 * (event.pageNum - 1))
.limit(20)
break;
case 4:
query = db.collection('post').aggregate()
.match({
//4指定
_id: event.id
})
.sort({
createTime: -1
})
.skip(20 * (event.pageNum - 1))
.limit(20)
break;
}
//使用聚合处理后续数据
let listData = await query
.lookup({
from: "user",
localField: "_openid",
foreignField: "_id",
as: "postList"
})//联表查询用户表
.replaceRoot({
newRoot: $.mergeObjects([$.arrayElemAt(['$postList', 0]), '$$ROOT'])
})//将用户表输出到根节点
.addFields({
day: $.dayOfMonth('$createTime'),
month: $.month('$createTime'),
year: $.year('$createTime'),
isLike: $.in([OPENID, '$likes']), //是否喜欢
isLiked: $.in([OPENID, '$liked']), //是否喜欢过
isAdmin: $.eq([OPENID, 'oy0T-4yk7lCRFGDefpFC4Yvx_ppU']),//是否管理员
isAuthor: $.eq(['$_openid', OPENID]),//是否为作者
like: $.size('$likes'), //喜欢该帖子数
face: $.switch({
branches: [
{ case: $.gte(['$feeling', 90]), then: 9 },
{ case: $.gte(['$feeling', 80]), then: 8 },
{ case: $.gte(['$feeling', 70]), then: 7 },
{ case: $.gte(['$feeling', 60]), then: 6 },
{ case: $.gte(['$feeling', 50]), then: 5 },
{ case: $.gte(['$feeling', 40]), then: 4 },
{ case: $.gte(['$feeling', 30]), then: 3 },
{ case: $.gte(['$feeling', 20]), then: 2 },
{ case: $.gte(['$feeling', 10]), then: 1 }
],
default: 0
}) //根据心情值判断对应表情
})
.project({
postList: 0,
userInfo: 0,
liked: 0,
likes: 0,
city: 0,
province: 0,
country: 0,
language: 0,
nlp: 0,
saveType: 0,
}) //清楚掉不需要的数据
.end()
return listData
这个不错,可以加社区精华
喜欢这个帖子的动作你是把用户id加到这个帖子的likes字段的,那如果是一个爆贴,喜欢的人很多,是不是会导致数据量很大,这个怎么处理?
你的post这张表,里边的like字段是一个数组,如果有一万个人喜欢,那么这个数组长度就是一万,这样的话会不会有影响
请问 聚合时候的怎么获取列表总数 使用count会有问题
请问聚合查询条数有上限吗,也就是aggregate后不加limit,能否取到全部符合条件的数据?