Рассмотрим коллекцию образцов документов , которые запрашиваются, как в вопросе:
{ _id: 1, type: "person", image: "i-1", age: 19, "fld": 12 },
{ _id: 2, type: "person", image: "i-2", age: 22, "fld": 121 },
{ _id: 3, type: "thing", image: "i-99", age: 29, "fld": 1212 }, // 'type' not 'person'
{ _id: 4, type: "person", age: 31, "fld": 12121 }, // 'image' missing
{ _id: 5, type: "person", image: "i-3", age: 13, "fld": 121212 },
{ _id: 6, type: "person", age: 43, "fld": 1212121 }, // 'image' missing
{ _id: 7, type: "person", image: "i-4", age: 20, "fld": 1 }
Нужно ли включать поля в индекс, если они у меня уже есть? фильтруется? Или это уже известно по выражению частичного фильтра, а я запрашиваю только то, что не исправлено?
Создать index :
db.collection.createIndex( { type: 1, age: -1 },
{
partialFilterExpression: {
type: 'person',
image: { $exists: true }
}
}
)
Примечание поля индекса только на type
и age
. Почему? Это объясняется в проверке использования индекса ниже.
запрос :
db.collection.find( { type: "person", image: { $exists: true } } ).sort( { age: -1 } )
Результат :
Запрос возвращает ожидаемые отфильтрованные документы и в отсортированном порядке.
{ "_id" : 2, "type" : "person", "image" : "i-2", "age" : 22, "fld" : 121 }
{ "_id" : 7, "type" : "person", "image" : "i-4", "age" : 20, "fld" : 1 }
{ "_id" : 1, "type" : "person", "image" : "i-1", "age" : 19, "fld" : 12 }
{ "_id" : 5, "type" : "person", "image" : "i-3", "age" : 13, "fld" : 121212 }
Проверка использования индекса:
Использование индекса можно проверить, сгенерировав план запроса с использованием explain
Метод:
db.collection.find( { type: "person", image: { $exists: true } } ).sort( { age: -1 } ).explain()
Выходные данные плана показывают использование индекса для операций сортировки фильтра и . Это отмечается как IXSCAN (индексированное сканирование) и отсутствие этапа SORT в плане. Это правильное использование индекса для этого запроса.
В определении индекса два поля type
+ age
задают составной индекс. Для этого требуется, чтобы индекс применялся к type
(для фильтрации) и age
(для сортировки). Поле image
нельзя указать в определении индекса, так как оно не используется с условием равенства (использует $exists
); если указано, индекс не будет использоваться для следующего отсортированного поля (из документации ):
Индекс может поддерживать операции сортировки в подмножестве без префикса ключа индекса шаблон. Для этого запрос должен включать условия равенства для всех префиксных ключей, предшествующих ключам сортировки.
План запроса (часть его):
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test.persons",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"type" : {
"$eq" : "person"
}
},
{
"image" : {
"$exists" : true
}
}
]
},
"queryHash" : "25E877F5",
"planCacheKey" : "C9D745BE",
"winningPlan" : {
"stage" : "FETCH",
"filter" : {
"image" : {
"$exists" : true
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"type" : 1,
"age" : -1
},
"indexName" : "type_1_age_-1",
"isMultiKey" : false,
"multiKeyPaths" : {
"type" : [ ],
"age" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : true,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"type" : [
"[\"person\", \"person\"]"
],
"age" : [
"[MaxKey, MinKey]"
]
}
}
}, ...