我正在研究Golang项目(db MongoDB)。我已经执行了以下查询,但是加载数据花费了太多时间。在这种情况下,我将从多个阶段的2个集合中获取数据。
db.getCollection('Collection1').aggregate([
{
"$lookup": {
"localField": "uid",
"from": "collection2",
"foreignField": "_id",
"as": "user_info"
}
},
{
"$unwind": "$user_info"
},
{
"$lookup": {
"localField": "cid",
"from": "collection3",
"foreignField": "_id",
"as": "cust_info"
}
},
{
"$lookup": {
"from": "logs",
"let": {"id": "$_id"},
"pipeline": [
{"$match": {"$expr": {"$eq": ["$$id", "$log_id"]}}},
{"$sort": {"log_type": 1}}],
"as": "logs_data"
}
},
{
"$sort": {"logs_data.logged_on":-1}
},
{
"$skip": 1
},
{
"$limit": 2
},
])
我的要求是在同一查询中添加2种时间排序:
"$sort": {"log_type": 1}}
"$sort": {"logs_data.logged_on":-1}
为此,我尝试了以下索引:
{"logged_on" : -1}
{"log_id":1, "log_type":1}
但是查询仍然需要6-7秒的时间来执行。
如果我删除了"$sort": {"logs_data.logged_on":-1}
,那么它的运行速度很快,但是这种排序会花费太多时间。
如何以及如何做才能缩短响应时间。
答案 0 :(得分:0)
该聚合正在做什么:
对于collection1中的每个文档,它是3个文档访存(加上#4中未知的访存次数),2个索引扫描和一个内存中排序。
如果collection1中有大量文档,那就是大量的工作,这浪费了除2个文档之外的所有文档。
如果可以安全地假设logs
中的每个文档都包含一个映射回log_id
的{{1}},则可以:
collection1
上创建索引{logged_on:1, log_id:1}
排序logged_on: 1
(这使聚合的第一部分完全由上述索引覆盖){logged_on:1, log_id:1, _id:0}
分组,取log_id
的{{1}}值$first
排序(分组不影响排序)logged_on
与本地logged_on: 1
外部collection1
进行查找