Все зависит от оптимизатора планировщика запросов MongoDB:
Операции конвейера агрегации имеют фазу оптимизации, которая пытается изменить форму конвейера для повышения производительности.
Чтобы увидеть, как оптимизатор преобразовывает конкретный конвейер агрегации, включив параметр объяснение в метод db.collection.aggregate ().
https://docs.mongodb.com/manual/core/aggregation-pipeline-optimization/
Создайте индекс для poDetailsId
и выполните этот запрос:
db.getCollection('collection').explain().aggregate([
{
$unwind: "$idList"
},
{
$match: {
'idList.isDispacthed': true,
"poDetailsId" : ObjectId("5dc7ac15720a2772c7b7666f")
}
}
])
{
"stages" : [
{
"$cursor" : {
"query" : {
"poDetailsId" : {
"$eq" : ObjectId("5dc7ac15720a2772c7b7666f")
}
},
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test.collection",
"indexFilterSet" : false,
"parsedQuery" : {
"poDetailsId" : {
"$eq" : ObjectId("5dc7ac15720a2772c7b7666f")
}
},
"queryHash" : "2CF7E390",
"planCacheKey" : "A8739F51",
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"poDetailsId" : 1.0
},
"indexName" : "poDetailsId_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"poDetailsId" : []
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"poDetailsId" : [
"[ObjectId('5dc7ac15720a2772c7b7666f'), ObjectId('5dc7ac15720a2772c7b7666f')]"
]
}
}
},
"rejectedPlans" : []
}
}
},
{
"$unwind" : {
"path" : "$idList"
}
},
{
"$match" : {
"idList.isDispacthed" : {
"$eq" : true
}
}
}
],
"ok" : 1.0
}
Как видите, MongoDB изменит эту агрегацию на:
db.getCollection('collection').aggregate([
{
$match: { "poDetailsId" : ObjectId("5dc7ac15720a2772c7b7666f") }
}
{
$unwind: "$idList"
},
{
$match: { 'idList.isDispacthed': true }
}
])
Логически, $match -> $unwind -> $match
лучше, поскольку вы фильтруете (по индексу) подмножество записей вместо полного сканирования (работа со 100 сопоставленными документами ≠ всеми документами).
Если для операции агрегирования требуется только подмножество данных в коллекции, используйте этапы $match
, $limit
и $skip
, чтобы ограничить документы, которые вводятся в начале трубопровод. При размещении в начале конвейера операции $match
используют подходящие индексы для сканирования только соответствующих документов в коллекции .
https://docs.mongodb.com/manual/core/aggregation-pipeline/#early -фильтрация
После манипулирования документами MongoDB не может применять индексы.