我有以下查询:
db.Visitor.aggregate([
{"$sort":{"updatedAt":-1}},
{"$match":{
"$and":[
{"events.platformId":"8"},
{"events.applicationId":{"$in":["354","325","373","177","379","417","415","416"]}},
{"events.date":{"$gte":ISODate("2018-01-26 15:23:00")}},
{"events.date":{"$lte":ISODate("2018-01-26 23:59:59")}}
]
}},
{"$project":{
"events":{
"$filter":{
"input":"$events",
"as":"event",
"cond":{
"$and":[
{"$eq":["$$event.platformId","8"]},
{"$in":["$$event.applicationId",["354","325","373","177","379","417","415","416"]]},
{"$gte":["$$event.date",ISODate("2018-01-26 15:23:00")]},
{"$lte":["$$event.date",ISODate("2018-01-26 23:59:59")]}
]
}
}
}
}},
{"$limit":15},
], {"maxTimeMS": 2500}).pretty()
它失败,因为它达到最大执行时间。如果我把它排除在外,它会以毫秒为单位返回。
我认为它可能是一个索引问题,但它已经存在:
{
"v" : 1,
"key" : {
"updatedAt" : -1
},
"name" : "expiration_ttl",
"ns" : "analytics.Visitor",
"expireAfterSeconds" : NumberLong(1296000)
}
你有任何线索吗?
谢谢:)
编辑:
经过一个周末的思考后,我提出了在$sort
和$match
之间创建一个步骤的想法,创建了一个额外的$match
过滤集合中{{1}的文档在updatedAt
或events.date
(前requests.date
)中指定的范围内。通过这种方式,查询将不会花费大量时间,因为结果集合比原始集合小得多,即使没有每个匹配条件属性的索引也能使匹配工作。
答案 0 :(得分:0)
将$sort
阶段移至$limit
之前的末尾。它应该触发sort-limit coalescence:
db.Visitor.aggregate([
{"$match":{
...
}},
{"$project":{
"events":{
...
},
"updatedAt": 1
}},
{"$sort":{"updatedAt":-1}},
{"$limit":15},
], {"maxTimeMS": 2500}).pretty()
使用hint
选项使用不同的索引对其进行基准测试:
db.Visitor.aggregate(
[...],
{"maxTimeMS": 2500, hint: "expiration_ttl"}
).pretty()