最近leader让我针对线上一个查询进行优化。举一个相似的例子,以如下的书籍信息文档为例,需要注意的是一本书可能会有多个作者。
业务上的需求是获取指定的50个作者最新出版的的书籍。在优化前,原先的代码逻辑是每次访问数据库获取一个作者参与的图书,按照时间倒序排序,分页取第一条信息。那么完成这个需求需要访问50次mongodb,生产环境这个业务总共耗时5s。leader让我优化到1S内。
这个查询的瓶颈主要是在IO次数上,是否可以访问一次数据库就能得到结果呢。笔者最先想到的是group by操作。以作者id进行group by,但是难点在于每个分组内部都要进行排序,然后取每个分组的第一条数据。Mongodb的分组聚合查询不支持组内排序的操作。
经过思考笔者采用如下的设计,在分组前先对时间进行倒序排序,随后再进行分组,这样获取的每个分组都是按照时间倒序排序的
db.book.aggregate([
{
"$match": {
"authors": {
"$in": ["author1", "author2"]
},
"time": {
"$gte": "20190101",
"$lte": "20191201"
}
}
},
{
"$unwind": "$authors"