Mongo version : 3.4.3-10-g865d2fb
I have a request like this :
db.getCollection('c_zop_operations').find({
"a":{
"$in":[
"O",
"S",
"P"
]
},
"$or":[
{
"b":"008091",
"c":"1187",
"d":"F",
"e":ISODate("2018-07-22T22:00:00.000Z")
},
... x 39 elements in $or statement
]
}).explain("executionStats")
The request during 16 seconds and explain returns these results :
155769 documents parse in index !!!
{
"queryPlanner" : {
"plannerVersion" : 1,
...
"indexFilterSet" : false,
"parsedQuery" : {
...
},
"winningPlan" : {
"stage" : "FETCH",
"filter" : {
"$or" : [
{
"$and" : [
{
"c" : {
"$eq" : "1187"
}
},
{
"d" : {
"$eq" : "F"
}
},
{
"b" : {
"$eq" : "008091"
}
},
{
"e" : {
"$eq" : ISODate("2018-07-22T22:00:00.000Z")
}
}
]
},
x 39 times
...
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"a" : 1
},
"indexName" : "a",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"a" : [
"[\"O\", \"O\"]",
"[\"P\", \"P\"]",
"[\"S\", \"S\"]"
]
}
}
},
"rejectedPlans" : [
...
]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 0,
"executionTimeMillis" : 16010,
"totalKeysExamined" : 155769,
"totalDocsExamined" : 155769,
...
}
...
}
In my collection, I have a lot of indexes (65) and my collection contains 3 millions of documents.
Only two indexes interest me here :
aIndex : { "a" : 1 }
And
beIndex: { "b" : 1, "e" : 1 }
By default, mongo use { "a" : 1 } and the request takes 16 seconds.
If I use hint(beIndex), the request takes 0,011 second and totalKeysExamined = 0 and totalDocsExamined = 0.
Why MongoDB don't use the beIndex that is more effective ?
This behavior is a known bug. See SERVER-13732. This was fixed in MongoDB 3.6.
As a workaround, distributing the top-level filter on a into each $or clause should allow the query planner to make a better index choice.
I have a aggregate pipeline that takes over 5 seconds to return 200 rows.
I'm trying to optimize my current pipeline using explain("executionStats").
This is my pipeline:
db.getCollection("content_topics").explain("executionStats").aggregate([{
"$lookup": {
from: "users",
localField: "creator",
foreignField: "_id",
as: "user"
}
},
{
$unwind: "$user"
},
{
"$match": {
created_at: {
"$gte": 1528914600,
"$lte": 1534271400
},
dash_status: 3,
language: "hi",
parent_topic_id: {
"$eq": null
},
status: 1,
"user.device_os": {
"$ne": "BOT"
}
}
},
{
"$sort": {
created_at: -1
}
},
{
"$addFields": {
user_handle: "$user.handle",
user_phone: "$user.phone",
user_status: "$user.status"
}
},
{
"$project": {
topic_id: 1,
n_vokes: 1,
message: 1,
title: 1,
language: 1,
description: 1,
voice_desc: 1,
image: 1,
image_share: 1,
hashtag: 1,
location: 1,
default_text: 1,
creator: 1,
created_at: 1,
status: 1,
ref_id: 1,
weightage: 1,
username: 1,
slug_generated: 1,
user_handle: 1,
user_phone: 1,
user_status: 1
}
},
{
"$skip": 0
},
{
"$limit": 200
}
]);
And this is what mongo explain()ed:
{
"stages" : [
{
"$cursor" : {
"query" : {
"$and" : [
{
"created_at" : {
"$gte" : 1528914600.0
}
},
{
"created_at" : {
"$lte" : 1534271400.0
}
},
{
"dash_status" : {
"$eq" : 3.0
}
},
{
"language" : {
"$eq" : "hi"
}
},
{
"parent_topic_id" : {
"$eq" : null
}
},
{
"status" : {
"$eq" : 1.0
}
}
]
},
"fields" : {
"created_at" : 1.0,
"creator" : 1.0,
"default_text" : 1.0,
"description" : 1.0,
"hashtag" : 1.0,
"image" : 1.0,
"image_share" : 1.0,
"language" : 1.0,
"location" : 1.0,
"message" : 1.0,
"n_vokes" : 1.0,
"ref_id" : 1.0,
"slug_generated" : 1.0,
"status" : 1.0,
"title" : 1.0,
"topic_id" : 1.0,
"user.handle" : 1.0,
"user.phone" : 1.0,
"user.status" : 1.0,
"user_handle" : 1.0,
"user_phone" : 1.0,
"user_status" : 1.0,
"username" : 1.0,
"voice_desc" : 1.0,
"weightage" : 1.0,
"_id" : 1.0
},
"queryPlanner" : {
"plannerVersion" : 1.0,
"namespace" : "vokalapp.content_topics",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"dash_status" : {
"$eq" : 3.0
}
},
{
"language" : {
"$eq" : "hi"
}
},
{
"parent_topic_id" : {
"$eq" : null
}
},
{
"status" : {
"$eq" : 1.0
}
},
{
"created_at" : {
"$lte" : 1534271400.0
}
},
{
"created_at" : {
"$gte" : 1528914600.0
}
}
]
},
"winningPlan" : {
"stage" : "FETCH",
"filter" : {
"parent_topic_id" : {
"$eq" : null
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"dash_status" : 1.0,
"status" : 1.0,
"language" : 1.0,
"parent_topic_id" : 1.0,
"created_at" : 1.0
},
"indexName" : "index_for_dashboard",
"isMultiKey" : false,
"multiKeyPaths" : {
"dash_status" : [
],
"status" : [
],
"language" : [
],
"parent_topic_id" : [
],
"created_at" : [
]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2.0,
"direction" : "forward",
"indexBounds" : {
"dash_status" : [
"[3.0, 3.0]"
],
"status" : [
"[1.0, 1.0]"
],
"language" : [
"[\"hi\", \"hi\"]"
],
"parent_topic_id" : [
"[null, null]"
],
"created_at" : [
"[1528914600.0, 1534271400.0]"
]
}
}
},
"rejectedPlans" : [
{
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"dash_status" : {
"$eq" : 3.0
}
},
{
"language" : {
"$eq" : "hi"
}
},
{
"parent_topic_id" : {
"$eq" : null
}
},
{
"status" : {
"$eq" : 1.0
}
}
]
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"created_at" : 1.0
},
"indexName" : "created_at_index",
"isMultiKey" : false,
"multiKeyPaths" : {
"created_at" : [
]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2.0,
"direction" : "forward",
"indexBounds" : {
"created_at" : [
"[1528914600.0, 1534271400.0]"
]
}
}
},
{
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"dash_status" : {
"$eq" : 3.0
}
},
{
"parent_topic_id" : {
"$eq" : null
}
}
]
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"language" : 1.0,
"status" : 1.0,
"created_at" : 1.0,
"answers.type" : 1.0
},
"indexName" : "language_status_created_at_answer_type_index",
"isMultiKey" : true,
"multiKeyPaths" : {
"language" : [
],
"status" : [
],
"created_at" : [
],
"answers.type" : [
"answers"
]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2.0,
"direction" : "forward",
"indexBounds" : {
"language" : [
"[\"hi\", \"hi\"]"
],
"status" : [
"[1.0, 1.0]"
],
"created_at" : [
"[1528914600.0, 1534271400.0]"
],
"answers.type" : [
"[MinKey, MaxKey]"
]
}
}
},
{
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"dash_status" : {
"$eq" : 3.0
}
},
{
"parent_topic_id" : {
"$eq" : null
}
}
]
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"language" : -1.0,
"status" : -1.0,
"weightage" : -1.0,
"created_at" : -1.0
},
"indexName" : "language_status_weightage_created_at_index",
"isMultiKey" : false,
"multiKeyPaths" : {
"language" : [
],
"status" : [
],
"weightage" : [
],
"created_at" : [
]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2.0,
"direction" : "forward",
"indexBounds" : {
"language" : [
"[\"hi\", \"hi\"]"
],
"status" : [
"[1.0, 1.0]"
],
"weightage" : [
"[MaxKey, MinKey]"
],
"created_at" : [
"[1534271400.0, 1528914600.0]"
]
}
}
}
]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 7072.0,
"executionTimeMillis" : 984.0,
"totalKeysExamined" : 7072.0,
"totalDocsExamined" : 7072.0,
"executionStages" : {
"stage" : "FETCH",
"filter" : {
"parent_topic_id" : {
"$eq" : null
}
},
"nReturned" : 7072.0,
"executionTimeMillisEstimate" : 40.0,
"works" : 7073.0,
"advanced" : 7072.0,
"needTime" : 0.0,
"needYield" : 0.0,
"saveState" : 63.0,
"restoreState" : 63.0,
"isEOF" : 1.0,
"invalidates" : 0.0,
"docsExamined" : 7072.0,
"alreadyHasObj" : 0.0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 7072.0,
"executionTimeMillisEstimate" : 0.0,
"works" : 7073.0,
"advanced" : 7072.0,
"needTime" : 0.0,
"needYield" : 0.0,
"saveState" : 63.0,
"restoreState" : 63.0,
"isEOF" : 1.0,
"invalidates" : 0.0,
"keyPattern" : {
"dash_status" : 1.0,
"status" : 1.0,
"language" : 1.0,
"parent_topic_id" : 1.0,
"created_at" : 1.0
},
"indexName" : "index_for_dashboard",
"isMultiKey" : false,
"multiKeyPaths" : {
"dash_status" : [
],
"status" : [
],
"language" : [
],
"parent_topic_id" : [
],
"created_at" : [
]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2.0,
"direction" : "forward",
"indexBounds" : {
"dash_status" : [
"[3.0, 3.0]"
],
"status" : [
"[1.0, 1.0]"
],
"language" : [
"[\"hi\", \"hi\"]"
],
"parent_topic_id" : [
"[null, null]"
],
"created_at" : [
"[1528914600.0, 1534271400.0]"
]
},
"keysExamined" : 7072.0,
"seeks" : 1.0,
"dupsTested" : 0.0,
"dupsDropped" : 0.0,
"seenInvalidated" : 0.0
}
}
}
}
},
{
"$lookup" : {
"from" : "users",
"as" : "user",
"localField" : "creator",
"foreignField" : "_id",
"unwinding" : {
"preserveNullAndEmptyArrays" : false
},
"matching" : {
"$nor" : [
{
"device_os" : {
"$eq" : "BOT"
}
}
]
}
}
},
{
"$sort" : {
"sortKey" : {
"created_at" : -1.0
},
"limit" : NumberLong(200)
}
},
{
"$addFields" : {
"user_handle" : "$user.handle",
"user_phone" : "$user.phone",
"user_status" : "$user.status"
}
},
{
"$project" : {
"_id" : true,
"hashtag" : true,
"voice_desc" : true,
"description" : true,
"location" : true,
"language" : true,
"topic_id" : true,
"image" : true,
"slug_generated" : true,
"n_vokes" : true,
"ref_id" : true,
"image_share" : true,
"message" : true,
"created_at" : true,
"default_text" : true,
"weightage" : true,
"user_handle" : true,
"title" : true,
"status" : true,
"creator" : true,
"user_status" : true,
"username" : true,
"user_phone" : true
}
}
],
"ok" : 1.0
}
This is after I created the index "index_for_dashboard" with the keys that I use in "$match". I also created an index for "device_os" from user collection. But to no dice, no improvements in the response time.
Possible culprits:
Is $lookup expensive. If it is can I fetch only the fields I need.
Can the indexing be done better. Should I use a different set of
fields?
Is $addField expensive. If it is I can offload it to
application level.
How should I troubleshoot(and understand) with the explain result to help myself optimize the query?
I can't make an educated call here, need some directions.
First, you want to make sure that you are running at least v3.6.3 of MongoDB because in v3.6 there's a new feature that allows $lookup to specify sub-pipelines. Those pipelines can actually use indexes, however, there was a bug which only got fixed in the version mentioned above.
The following should be as fast as things can get here:
db.getCollection("content_topics").createIndex({ created_at: -1, dash_status: 1, language: 1, parent_topic_id: 1, status: 1 }); // this index will get used by the main $match and the $sort stage
db.getCollection("users").createIndex({ device_os: 1 }); // this index will get used by the sub-pipeline in $lookup
db.getCollection("content_topics").aggregate([{
"$match": { // filter at the start in order to be able to use indexes
created_at: {
"$gte": 1528914600,
"$lte": 1534271400
},
dash_status: 3,
language: "hi",
parent_topic_id: {
"$eq": null
},
status: 1
// see the below $lookup stage in case you're wondering where the user filter went
}
},
{
"$sort": {
created_at: -1 // sort straight away so the index can be used
}
},
{
"$lookup": {
from: "users",
let: { "creator": "$creator" },
pipeline: [{ // use new v3.6 pipeline syntax to be able to leverage indexes
$match: {
$expr: {
$and: [
{ $eq: [ "$_id", "$$creator" ] },
{ $ne: [ "$device_os", "BOT" ] } // here is the "device_os" filter inside the pipeline so index can be used
]
}
}
}, {
$project: {
_id: 0, // "_id" field is not needed
user_handle: 1, // only those fields are of interest
user_phone: 1,
user_status: 1
}
}],
as: "user"
}
},
{
$unwind: "$user"
},
{
"$project": {
topic_id: 1,
n_vokes: 1,
message: 1,
title: 1,
language: 1,
description: 1,
voice_desc: 1,
image: 1,
image_share: 1,
hashtag: 1,
location: 1,
default_text: 1,
creator: 1,
created_at: 1,
status: 1,
ref_id: 1,
weightage: 1,
username: 1,
slug_generated: 1,
user_handle: "$user.handle", // no extra $addFields stage needed
user_phone: "$user.phone", // same here
user_status: "$user.status" // and here
}
},
{
"$skip": 0
},
{
"$limit": 200
}
]);
I am new to mongo and below query performs really slow with record set over 2 Million records
Query
db.testCollection.aggregate({
$match: {
active: {
$ne: false
}
}
}, {
$group: {
_id: {
productName: "$productName",
model: "$model",
version: "$version",
uid: "$uid"
},
total: {
$sum: 1
}
}
}, {
$project: {
total: 1,
model: "$_id.model",
version: "$_id.version",
uid: "$_id.uid",
productName: "$_id.productName"
}
}, {
$sort: {
model: 1
}
})
explain()
{
"stages" : [
{
"$cursor" : {
"query" : {
"active" : {
"$ne" : false
}
},
"fields" : {
"version" : 1,
"productName" : 1,
"model" : 1,
"uid" : 1,
"_id" : 0
},
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "fms2.device",
"indexFilterSet" : false,
"parsedQuery" : {
"$nor" : [
{
"active" : {
"$eq" : false
}
}
]
},
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"active" : 1
},
"indexName" : "active",
"isMultiKey" : false,
"multiKeyPaths" : {
"active" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"active" : [
"[MinKey, false)",
"(false, MaxKey]"
]
}
}
},
"rejectedPlans" : [ ]
}
}
},
{
"$group" : {
"_id" : {
"productName" : "$productName",
"model" : "$model",
"version" : "$version",
"uid" : "$uid"
},
"total" : {
"$sum" : {
"$const" : 1
}
}
}
},
{
"$project" : {
"_id" : true,
"total" : true,
"model" : "$_id.model",
"version" : "$_id.version",
"uid" : "$_id.uid",
"productName" : "$_id.productName"
}
},
{
"$sort" : {
"sortKey" : {
"model" : 1
}
}
}
],
"ok" : 1
}
Is there a way to optimize this query more ? I had a look into https://docs.mongodb.com/manual/core/aggregation-pipeline-optimization/ as well but most of the stated suggestions are not applicable for this query.
Not sure if it matters, result of this aggregation ends up with only 20-30 records.
I have a collection where my documents looks like:
{
"_id" : ObjectId("591dbe4a77d4ede22d765250"),
"name" : [
{
"de" : true,
"text" : "Brunhilde"
},
{
"sk" : true,
"text" : "Šimon"
}
]
}
I have defined an index as:
> db.names.createIndex({ 'name.de': 1, 'name.text': 1 }, { name: 'name_de', partialFilterExpression: { 'name.de': { $exists: true } }, collation: { locale: 'de' } });
When I do a query like:
> db.names.find({ 'name.de': true, 'name.text': 'Rüdi' }).collation({ locale: 'de' });
The explain plan looks like:
"winningPlan" : {
"stage" : "FETCH",
"filter" : {
"name.text" : {
"$eq" : "Rüdi"
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"name.de" : 1,
"name.text" : 1
},
"indexName" : "name_de",
"collation" : {
"locale" : "de",
"caseLevel" : false,
"caseFirst" : "off",
"strength" : 3,
"numericOrdering" : false,
"alternate" : "non-ignorable",
"maxVariable" : "punct",
"normalization" : false,
"backwards" : false,
"version" : "57.1"
},
"isMultiKey" : true,
"multiKeyPaths" : {
"name.de" : [
"name"
],
"name.text" : [
"name"
]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : true,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"name.de" : [
"[true, true]"
],
"name.text" : [
"[MinKey, MaxKey]"
]
}
}
}
It does IXSCAN followed by FETCH stage with filter. I've already created an question about the filter here.
The more interesting is what will happen when I just change the matching part of the query to:
> db.names.find({ 'name.de': { $exists: true }, 'name.text': 'Rüdi' }).collation({ locale: 'de' });
i.e. expression 'name.de': { $exists: true } should be still subset of partialFilterExpression. As stated in documentation:
To use the partial index, a query must contain the filter expression (or a modified filter expression that specifies a subset of the filter expression) as part of its query condition.
But the explain plan looks like this:
...
"winningPlan" : {
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"name.de" : {
"$exists" : true
}
},
{
"name.text" : {
"$eq" : "Rüdi"
}
}
]
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"name.de" : 1,
"name.text" : 1
},
"indexName" : "name_de",
"collation" : {
"locale" : "de",
"caseLevel" : false,
"caseFirst" : "off",
"strength" : 3,
"numericOrdering" : false,
"alternate" : "non-ignorable",
"maxVariable" : "punct",
"normalization" : false,
"backwards" : false,
"version" : "57.1"
},
"isMultiKey" : true,
"multiKeyPaths" : {
"name.de" : [
"name"
],
"name.text" : [
"name"
]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : true,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"name.de" : [
"[MinKey, MaxKey]"
],
"name.text" : [
"[MinKey, MaxKey]"
]
}
}
}
...
As you can see index is used, but the whole filtering is happening in FETCH stage.
Question is: why the filtering is done in FETCH stage and what is so different between these 2 queries that MongoDB them differently?
Additionaly, sort query with $exists as:
> db.names.find({ 'name.de': { $exists: true } }).sort({ 'name.text': 1 }).collation({ locale: "de" })
Behaves the same, whole filtering and sorting is done after IXSCAN stage:
...
"winningPlan" : {
"stage" : "SORT",
"sortPattern" : {
"name.text" : 1
},
"inputStage" : {
"stage" : "SORT_KEY_GENERATOR",
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"name.de" : {
"$exists" : true
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"name.de" : 1,
"name.text" : 1
}
...
It even produces the incorrect results, while index is not used for sorting.
I have an aggregate on a collection with about 1.6M of registers. That consult is a simple example of other more complex, but illustrate the poor optimization of index used in my opinion.
db.getCollection('cbAlters').runCommand("aggregate", {pipeline: [
{
$match: { cre_carteraId: "31" }
},
{
$group: { _id: { ca_tramomora: "$cre_tramoMora" },
count: { $sum: 1 } }
}
]})
That query toke about 5 sec. The colleccion have 25 indexes configured to differents consults. The one used according to query explain is:
{
"v" : 1,
"key" : {
"cre_carteraId" : 1,
"cre_periodo" : 1,
"cre_tramoMora" : 1,
"cre_inactivo" : 1
},
"name" : "cartPerTramInact",
"ns" : "basedatos.cbAlters"
},
I created an index adjusted to this particular query:
{
"v" : 1,
"key" : {
"cre_carteraId" : 1,
"cre_tramoMora" : 1
},
"name" : "cartPerTramTest",
"ns" : "basedatos.cbAlters"
}
The query optimizer reject this index, and suggests me to use the initial index. Output of my query explain seem like this:
{
"waitedMS" : NumberLong(0),
"stages" : [
{
"$cursor" : {
"query" : {
"cre_carteraId" : "31"
},
"fields" : {
"cre_tramoMora" : 1,
"_id" : 0
},
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "basedatos.cbAlters",
"indexFilterSet" : false,
"parsedQuery" : {
"cre_carteraId" : {
"$eq" : "31"
}
},
"winningPlan" : {
"stage" : "PROJECTION",
"transformBy" : {
"cre_tramoMora" : 1,
"_id" : 0
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"cre_carteraId" : 1,
"cre_periodo" : 1,
"cre_tramoMora" : 1,
"cre_inactivo" : 1
},
"indexName" : "cartPerTramInact",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"cre_carteraId" : [
"[\"31\", \"31\"]"
],
"cre_periodo" : [
"[MinKey, MaxKey]"
],
"cre_tramoMora" : [
"[MinKey, MaxKey]"
],
"cre_inactivo" : [
"[MinKey, MaxKey]"
]
}
}
},
"rejectedPlans" : [
{
"stage" : "PROJECTION",
"transformBy" : {
"cre_tramoMora" : 1,
"_id" : 0
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"cre_carteraId" : 1,
"cre_tramoMora" : 1
},
"indexName" : "cartPerTramTest",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"cre_carteraId" : [
"[\"31\", \"31\"]"
],
"cre_tramoMora" : [
"[MinKey, MaxKey]"
]
}
}
}
]
}
}
},
{
"$group" : {
"_id" : {
"ca_tramomora" : "$cre_tramoMora"
},
"count" : {
"$sum" : {
"$const" : 1.0
}
}
}
}
],
"ok" : 1.0
}
Then, why optimizer prefers an index less adjusted? Should indexFilterSet (result filtered for index) be true for this aggregate?
How can I improve this index, or something goes wrong with the query?
I do not have much experience with mongoDB, I appreciate any help
As long as you have index cartPerTramInact, optimizer won't use your cartPerTramTest index because first fields are same and in same order.
This goes with other indexes too. When there is indexes what have same keys at same order (like a.b.c.d, a.b.d, a.b) and you query use fields a.b, it will favour that a.b.c.d. Anyway you don't need that index a.b because you already have two indexes what covers a.b (a.b.c.d and a.b.d)
Index a.b.d is used only when you do query with those fields a.b.d, BUT if a.b is already very selective, it's probably faster to do select with index a.b.c.d using only part a.b and do "full table scan" to find that d
There is a hint option for aggregations that can help with the index...
See https://www.mongodb.com/docs/upcoming/reference/method/db.collection.aggregate/#mongodb-method-db.collection.aggregate