在my comment的基础上展开,您描述的情况将是not,结果是指数为multikey (in MongoDB terminology).如文档中所述,多键索引产生于以下情况:
如果任何索引字段是数组,MongoDB会自动创建一个多键索引;您不需要显式指定多键类型.
文档中没有字段,因此索引的字段都不是array.通过下面的测试,我们可以证明索引不是多键的:
test> db.foo.drop()
false
test> db.foo.insert({ _id: ObjectId(), Title: "", Description: "", Scheduling: { From: 20230202, To: 20230201, MagicValue: 12 }, Mandatory: true, Type: "None" })
{
acknowledged: true,
insertedIds: { '0': ObjectId("649de6208c8616ab438dd397") }
}
test> db.foo.createIndex({ _id: 1, Title: 1, "Scheduling.From": 1 })
_id_1_Title_1_Scheduling.From_1
test> db.foo.find().hint("_id_1_Title_1_Scheduling.From_1").explain().queryPlanner.winningPlan.inputStage
{
stage: 'IXSCAN',
keyPattern: { _id: 1, Title: 1, 'Scheduling.From': 1 },
indexName: '_id_1_Title_1_Scheduling.From_1',
isMultiKey: false,
multiKeyPaths: { _id: [], Title: [], 'Scheduling.From': [] },
isUnique: false,
isSparse: false,
isPartial: false,
indexVersion: 2,
direction: 'forward',
indexBounds: {
_id: [ '[MinKey, MaxKey]' ],
Title: [ '[MinKey, MaxKey]' ],
'Scheduling.From': [ '[MinKey, MaxKey]' ]
}
}
最具体地说,输出报告isMultiKey: false
.
相比之下,以下是针对多键复合索引所报告的内容:
> db.foo.drop()
false
test> db.foo.insert({_id:1, x: [1,2,3] })
{ acknowledged: true, insertedIds: { '0': 1 } }
test> db.foo.createIndex({_id:1, x:1})
_id_1_x_1
test> db.foo.find().hint("_id_1_x_1").explain().queryPlanner.winningPlan.inputStage
{
stage: 'IXSCAN',
keyPattern: { _id: 1, x: 1 },
indexName: '_id_1_x_1',
isMultiKey: true,
multiKeyPaths: { _id: [], x: [ 'x' ] },
isUnique: false,
isSparse: false,
isPartial: false,
indexVersion: 2,
direction: 'forward',
indexBounds: { _id: [ '[MinKey, MaxKey]' ], x: [ '[MinKey, MaxKey]' ] }
}
所以这considerations for multikey index bounds个都不适用于你的情况.
话虽如此,但还有一件事需要注意.您的索引以_id
字段为前缀,根据MongoDB的定义,该字段是唯一的.如果您打算使用此索引的一个或多个查询在_id
字段上具有相等条件,则必须强制数据库使用它.当前版本的MongoDB在任何时候看到这种情况都会默认使用默认的{ _id: 1 }
索引.
我们可以看到,通过恢复所需的索引并运行.explain()
个相关查询:
test> db.foo.drop()
false
test> db.foo.createIndex({ _id: 1, Title: 1, "Scheduling.From": 1 })
_id_1_Title_1_Scheduling.From_1
test> db.foo.find({_id: 123, Title: 456, "Scheduling.From": 789}).explain().queryPlanner.winningPlan
{
stage: 'FETCH',
filter: {
'$and': [
{ 'Scheduling.From': { '$eq': 789 } },
{ Title: { '$eq': 456 } }
]
},
inputStage: {
stage: 'IXSCAN',
keyPattern: { _id: 1 },
indexName: '_id_',
isMultiKey: false,
multiKeyPaths: { _id: [] },
isUnique: true,
isSparse: false,
isPartial: false,
indexVersion: 2,
direction: 'forward',
indexBounds: { _id: [ '[123, 123]' ] }
}
}
通过.hint()
强制使用索引表明,如果需要,可以使用(并且高效地使用)索引:
test> db.foo.find({_id: 123, Title: 456, "Scheduling.From": 789}).hint("_id_1_Title_1_Scheduling.From_1").explain().queryPlanner.winningPlan
{
stage: 'FETCH',
inputStage: {
stage: 'IXSCAN',
keyPattern: { _id: 1, Title: 1, 'Scheduling.From': 1 },
indexName: '_id_1_Title_1_Scheduling.From_1',
isMultiKey: false,
multiKeyPaths: { _id: [], Title: [], 'Scheduling.From': [] },
isUnique: false,
isSparse: false,
isPartial: false,
indexVersion: 2,
direction: 'forward',
indexBounds: {
_id: [ '[123, 123]' ],
Title: [ '[456, 456]' ],
'Scheduling.From': [ '[789, 789]' ]
}
}
}