在MongoDB的通配符索引中包含特定字段
在MongoDB中创建通配符索引时,您可以选择指定单个字段,所有字段或仅指定一些字段。
您可以使用该参数在通配符索引中包含或排除特定字段路径。本文提供了在通配符索引中包含特定字段的示例。wildcardProjection
示例文档
假设我们有一个包含以下文档的集合:pets
{ “_id” : 1, “name” : “Wag”, “details” : { “type” : “Dog”, “weight” : 20, “awards” : { “Florida Dog Awards” : “Top Dog”, “New York Marathon” : “Fastest Dog”, “Sumo 2020” : “Biggest Dog” } } } { “_id” : 2, “name” : “Fetch”, “details” : { “born” : ISODate(“2020-06-22T14:00:00Z”), “color” : “Black” } } { “_id” : 3, “name” : “Scratch”, “details” : { “eats” : [ “Mouse Porridge”, “Bird Soup”, “Caviar” ], “type” : “Cat”, “born” : ISODate(“2020-12-19T14:00:00Z”) } }
我们可以在整个集合上创建一个通配符索引,但只包含我们想要的字段。
创建索引
下面是一个示例:
db.pets.createIndex(
{ "$**" : 1 },
{
"wildcardProjection" : {
"details.type" : 1,
"details.born" : 1
}
}
)
输出:
{ “createdCollectionAutomatically” : false, “numIndexesBefore” : 1, “numIndexesAfter” : 2, “ok” : 1 }
该部分是创建通配符索引的部分,该部分是指定要包含哪些字段的部分。在本例中,我们包含了字段和字段。为它们指定值 显式将它们包含在索引中。{ "$**" : 1 }``wildcardProjection``details.type``details.born``1
查看索引
我们可以通过调用方法查看集合上的索引:getIndexes()
db.pets.getIndexes()
输出:
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_"
},
{
"v" : 2,
"key" : {
"$**" : 1
},
"name" : "$**_1",
"wildcardProjection" : {
"details.type" : 1,
"details.born" : 1
}
}
]我们可以看到有两个索引。
- 第一个索引在字段上。这是在创建集合时创建的(MongoDB在创建集合期间在_id字段上创建一个唯一的索引)。
_id - 第二个索引是我们的通配符索引。我们可以看到它已被自动命名,它包括我们指定的字段。
$**_1
测试索引
我们还可以运行一些查询来查看我们的索引是否会被使用。
理论上,以下查询应使用该索引:
db.pets.find( { "details.type" : "Dog" } )
为了测试这一点,我们可以附加方法来查看查询计划:explain()
db.pets.find( { "details.type" : "Dog" } ).explain()
输出:
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "PetHotel.pets",
"indexFilterSet" : false,
"parsedQuery" : {
"details.type" : {
"$eq" : "Dog"
}
},
"queryHash" : "F1C5286F",
"planCacheKey" : "5326DE93",
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"$_path" : 1,
"details.type" : 1
},
"indexName" : "$**_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"$_path" : [ ],
"details.type" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"$_path" : [
"[\"details.type\", \"details.type\"]"
],
"details.type" : [
"[\"Dog\", \"Dog\"]"
]
}
}
},
"rejectedPlans" : [ ]
},
"ok" : 1
}我们可以看到它在我们的索引中使用了索引扫描(IXSCAN)。
与此相反,当我们对_未_包含在索引中的字段运行查询时,会发生什么情况:
db.pets.find( { "details.awards.New York Marathon" : "Fastest Dog" } ).explain()
输出:
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "PetHotel.pets",
"indexFilterSet" : false,
"parsedQuery" : {
"details.awards.New York Marathon" : {
"$eq" : "Fastest Dog"
}
},
"queryHash" : "EC0D5185",
"planCacheKey" : "EC0D5185",
"winningPlan" : {
"stage" : "COLLSCAN",
"filter" : {
"details.awards.New York Marathon" : {
"$eq" : "Fastest Dog"
}
},
"direction" : "forward"
},
"rejectedPlans" : [ ]
},
"ok" : 1
}在本例中,它执行了集合扫描(COLLSCAN),因此正如预期的那样,它没有使用索引。