MongoDB: Aggregation ($sort)对一个集合的联合非常慢



我有几个集合,我需要执行联合,然后查询。然而,我意识到由于某些原因,这是非常缓慢的。这个解释并不是很有用,因为它只告诉我们第一个$match阶段是否被索引了。我使用的是这样的管道:

[
{
"$match": {
"$and": [
{ ... }
]
}
},
// repeat this chunk for each collection
{
"$unionWith": {
"coll": "anotherCollection",
"pipeline": [
{
"$match": {
"$and": [
{ ... }
]
}
},
]
}
},
// Then an overall limit/handle pagination for all the unioned results
// UPDATE: Realised the sort is the culprit
{ "$sort": { "createdAt": -1 } },
{ "$skip": 0},
{ "$limit": 50 }
]

有更好的方法来做这样的查询吗?mongo会并行地进行联合吗?有"DB视图"吗?我能用来获得所有集合的并集吗?

刚意识到添加排序后运行时间增加了。我怀疑它不能使用索引,因为它是在联合体?

是的,有一个方法。但这并不是微不足道的,您需要更改分页的方式。它需要更多的工程,因为您不仅要通过编号跟踪页面,还要通过最后找到的元素

来跟踪页面。如果你通过一个唯一标识符(通常是_id)和一个游标来过滤分页,你可以做早期过滤。

! !重要! !您需要跟踪找到的最后一项,而不是跳过一些元素。如果不这样做,就会失去分页的跟踪,并且可能永远不会返回某些数据,或者返回某些数据两次,这比慢得多

[
{
"$match": {
"$and": [
{ ... }
],
"_id":{"$gt": lastKnownIdOfCollectionA} // this will filter out everything you already saw, so no skip needed
}
},
{ "$sort": { "createdAt": -1 } }, // this sorting is indexed!
{ "$limit": 50 } // maybe you will take 0 but max 50, you don't care about the rest
// repeat this chunk for each collection
{
"$unionWith": {
"coll": "anotherCollection",
"pipeline": [
{
"$match": {
"$and": [
{ ... }
],
"_id":{"$gt": lastKnownIdOfCollectionB} // this will filter out everything you already saw, so no skip needed
}
},
{ "$sort": { "createdAt": -1 } }, // this sorting is indexed!
{ "$limit": 50 } // maybe you will take 0 but max 50, you don't care about the rest
]
}
},
// At this point you have MAX 100 elements, an index is not needed for sorting :)
{ "$sort": { "createdAt": -1 } },
{ "$skip": 0},
{ "$limit": 50 }
]

在本例中,我通过_id进行早期筛选,其中还包含createat时间戳。如果筛选与创建日期无关,则可能需要定义最适合的标识符。请记住,标识符必须是唯一的标识符,但您可以使用多个值组合(例如。createdAt + randomizedId)