У меня есть mongodb v4.2.2, размещенный на Atlas. Имеют коллекцию objects
и два поля в ней: metadata
как массив объектов, каждый объект имеет одно поле key
И второе поле с именем model
. Добавлен составной индекс model->metadata.key
как обычный. При запуске команды db db.objects.explain('executionStats').distinct('metadata.key',
{model: ObjectId('5e18aff58a5aaffdc3d6f26d')})
из консоли он не использует мой индекс model->metadata.key
и не использует DISTINCT_SCAN.
Но если я перенесу данные в другую коллекцию, скажем, что objectKeys
имеет два поля, такие как key
, model
, и снова добавит обычный составной индекс model->key
и команду run db.objectKeys.explain('executionStats').distinct('key', {model:
ObjectId('5e18aff58a5aaffdc3d6f26d')})
успешно применяет DISTINCT_SCAN и использует индекс.
- Вопрос. Как заставить MongoDB использовать индексы для поля с точечной нотацией во время отдельной операции?
ДЕТАЛИ ОБНОВЛЕНИЯ:
1.
db.objects.getIndexes();
{
"v" : 2,
"key" : {
"model" : 1,
"metadata.key" : 1,
"metadata.value" : 1
},
"name" : "model_1_metadata.key_1_metadata.value_1",
"ns" : "my_db.objects",
"background" : true
}
db.objects.explain('executionStats').distinct('metadata.key', {model: ObjectId('5e18aff58a5aaffdc3d6f26d')})
"executionStages" : {
"stage" : "FETCH",
"nReturned" : 0,
"executionTimeMillisEstimate" : 0,
"works" : 1,
"advanced" : 0,
"needTime" : 0,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"docsExamined" : 0,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 0,
"executionTimeMillisEstimate" : 0,
"works" : 1,
"advanced" : 0,
"needTime" : 0,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"keyPattern" : {
"model" : 1,
"metadata.key" : 1,
"metadata.value" : 1
},
"indexName" : "model_1_metadata.key_1_metadata.value_1",
"isMultiKey" : true,
"multiKeyPaths" : {
"model" : [ ],
"metadata.key" : [
"metadata"
],
"metadata.value" : [
"metadata"
]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"model" : [
"[ObjectId('5e18aff58a5aaffdc3d6f26d'), ObjectId('5e18aff58a5aaffdc3d6f26d')]"
],
"metadata.key" : [
"[MinKey, MaxKey]"
],
"metadata.value" : [
"[MinKey, MaxKey]"
]
},
"keysExamined" : 0,
"seeks" : 1,
"dupsTested" : 0,
"dupsDropped" : 0
}
}
2.
db.object_keys.getIndexes();
{
"v" : 2,
"key" : {
"models" : 1,
"key" : 1
},
"name" : "models_1_key_1",
"ns" : "my_db.object_keys",
"background" : true
},
db.object_keys.explain('executionStats').distinct('key', {models: ObjectId('5e18aff58a5aaffdc3d6f26d')})
"executionStages" : {
"stage" : "PROJECTION_COVERED",
"nReturned" : 0,
"executionTimeMillisEstimate" : 0,
"works" : 1,
"advanced" : 0,
"needTime" : 0,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"transformBy" : {
"_id" : 0,
"key" : 1
},
"inputStage" : {
"stage" : "DISTINCT_SCAN",
"nReturned" : 0,
"executionTimeMillisEstimate" : 0,
"works" : 1,
"advanced" : 0,
"needTime" : 0,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"keyPattern" : {
"models" : 1,
"key" : 1
},
"indexName" : "models_1_key_1",
"isMultiKey" : true,
"multiKeyPaths" : {
"models" : [
"models"
],
"key" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"models" : [
"[ObjectId('5e18aff58a5aaffdc3d6f26d'), ObjectId('5e18aff58a5aaffdc3d6f26d')]"
],
"key" : [
"[MinKey, MaxKey]"
]
},
"keysExamined" : 0
}
}
Итак, как вы можете видеть в первом случае, он использует сканирование индекса IXSCAN, а во втором - DISTINCT_SCAN, который считается более быстрым. Разница в том, что в первом случае поле metadata
является массивом объектов, а во втором случае поле key
является строкой