@Aaron_Lee1 ,
Look at the explain plans of each query:
When running the single count query which I actually prefare to use the count operation:
db.collection.count({A :true})
executionStats: {
executionSuccess: true,
nReturned: 0,
executionTimeMillis: 0,
totalKeysExamined: 1001,
totalDocsExamined: 0,
executionStages: {
stage: 'COUNT',
nReturned: 0,
executionTimeMillisEstimate: 0,
works: 1001,
advanced: 0,
needTime: 1000,
needYield: 0,
saveState: 1,
restoreState: 1,
isEOF: 1,
nCounted: 1000,
nSkipped: 0,
inputStage: {
stage: 'COUNT_SCAN',
nReturned: 1000,
Will return just an index scan on {A : 1} with no need to scan documents in my case I had 1000 A : true in the the collection.
When using facet look at the explain plan:
"nReturned": 1600,
"executionTimeMillis": 4,
"totalKeysExamined": 0,
"totalDocsExamined": 1600,
"executionStages": {
"stage": "PROJECTION_SIMPLE",
"nReturned": 1600,
"executionTimeMillisEstimate": 0,
"works": 1602,
"advanced": 1600,
"needTime": 1,
"needYield": 0,
"saveState": 2,
"restoreState": 2,
"isEOF": 1,
"transformBy": {
"A": 1,
"B": 1,
"C": 1,
"_id": 0
},
"inputStage": {
"stage": "COLLSCAN",
"nReturned": 1600,
"executionTimeMillisEstimate": 0,
"works": 1602,
"advanced": 1600,
"needTime": 1,
"needYield": 0,
"saveState": 2,
"restoreState": 2,
"isEOF": 1,
"direction": "forward",
"docsExamined": 1600
}
},
"allPlansExecution": []
}
},
"nReturned": 1600,
"executionTimeMillisEstimate": 2
},
{
"$facet": {
"countA": [
{
"$internalFacetTeeConsumer": {},
"nReturned": 1600,
"executionTimeMillisEstimate": 2
},
{
"$match": {
"A": {
"$eq": true
}
},
"nReturned": 1000,
"executionTimeMillisEstimate": 2
},
{
"$group": {
"_id": {
"$const": null
},
"count": {
"$sum": {
"$const": 1
}
}
},
"maxAccumulatorMemoryUsageBytes": {
"count": 80
},
"totalOutputDataSizeBytes": 237,
"usedDisk": false,
"spills": 0,
"nReturned": 1,
"executionTimeMillisEstimate": 2
},
{
"$project": {
"count": true,
"_id": false
},
"nReturned": 1,
"executionTimeMillisEstimate": 2
}
],
"countB": [
{
"$internalFacetTeeConsumer": {},
"nReturned": 1600,
"executionTimeMillisEstimate": 0
},
{
"$match": {
"B": {
"$eq": true
}
},
"nReturned": 500,
"executionTimeMillisEstimate": 0
},
{
"$group": {
"_id": {
"$const": null
},
"count": {
"$sum": {
"$const": 1
}
}
},
"maxAccumulatorMemoryUsageBytes": {
"count": 80
},
"totalOutputDataSizeBytes": 237,
"usedDisk": false,
"spills": 0,
"nReturned": 1,
"executionTimeMillisEstimate": 0
},
{
"$project": {
"count": true,
"_id": false
},
"nReturned": 1,
"executionTimeMillisEstimate": 0
}
],
"countC": [
{
"$internalFacetTeeConsumer": {},
"nReturned": 1600,
"executionTimeMillisEstimate": 0
},
{
"$match": {
"C": {
"$eq": true
}
},
"nReturned": 100,
"executionTimeMillisEstimate": 0
},
{
"$group": {
"_id": {
"$const": null
},
"count": {
"$sum": {
"$const": 1
}
}
},
"maxAccumulatorMemoryUsageBytes": {
"count": 80
},
"totalOutputDataSizeBytes": 237,
"usedDisk": false,
"spills": 0,
"nReturned": 1,
"executionTimeMillisEstimate": 0
},
{
"$project": {
"count": true,
"_id": false
},
"nReturned": 1,
"executionTimeMillisEstimate": 0
}
]
},
"nReturned": 1,
"executionTimeMillisEstimate": 2
}
],
"serverInfo": {
"host": "atlas-rg2tcy-shard-00-02.uvwhr.mongodb.net",
"port": 27017,
"version": "6.1.0",
"gitVersion": "0ca11aca38c75d3c8fb5bac5bd103b950718a896"
It actually does a collection scan for the full collection. And need to read the documents which are much larger than the index.
I think that if you need this one in one query you are way better using unionWith rather than facet:
db.collection.aggregate([{
$match: {
A: true
}
}, {
$count: 'countA'
}, {
$unionWith: {
coll: 'collection',
pipeline: [
{
$match: {
B: true
}
},
{
$count: 'countB'
}
]
}
}, {
$unionWith: {
coll: 'collection',
pipeline: [
{
$match: {
C: true
}
},
{
$count: 'countC'
}
]
}
}])
Ty
Pavel