MongoDB容許深刻文檔內部,對嵌套字段和數組創建索引;
嵌套對象和數組字段能夠和複合索引中的頂級字段一塊兒使用,多數狀況下與「正常」索引字段的行爲也是一致的。
考慮如下文檔集合(user ):
html
db.user.insertMany(
[
{
"address": {
"province": "HeNan",
"city": "ZhengZhou",
"pincode": "123"
},
"tags": [
"music",
"cricket",
"blogs"
],
"name": "fly"
},
{
"address": {
"province": "HeBei",
"city": "HanDan",
"pincode": "234"
},
"tags": [
"music",
"basket",
"blogs"
],
"name": "chen"
},
{
"address": {
"province": "ChongQing",
"city": "ChongQing",
"pincode": "456"
},
"tags": [
"music",
"writing",
"running"
],
"name": "wang"
}
]
)
以上文檔包含了 address 子文檔和 tags 數組。git
db.user.ensureIndex({"tags":1})
db.user.find({tags:"music"})
db.user.find({tags:"music"}).explain()
/* 1 */
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "mongotest.user",
"indexFilterSet" : false,
"parsedQuery" : {
"tags" : {
"$eq" : "music"
}
},
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"tags" : 1.0
},
"indexName" : "tags_1",
"isMultiKey" : true,
"multiKeyPaths" : {
"tags" : [
"tags"
]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"tags" : [
"[\"music\", \"music\"]"
]
}
}
},
"rejectedPlans" : []
},
"serverInfo" : {
"host" : "kf-PC",
"port" : 27017,
"version" : "3.4.9",
"gitVersion" : "876ebee8c7dd0e2d992f36a848ff4dc50ee6603e"
},
"ok" : 1.0
}
stage的類型的意義
mongodb的文檔中列出了前4種類型,還有一些沒有列出來,可是會比較常見,這裏一併解釋一下。
COLLSCAN :全表掃描
IXSCAN:索引掃描
FETCH::根據索引去檢索指定document
SHARD_MERGE:各個分片返回數據進行merge
SORT:代表在內存中進行了排序(與前期版本的scanAndOrder:true一致)
SORT_MERGE:代表在內存中進行了排序後再合併
LIMIT:使用limit限制返回數
SKIP:使用skip進行跳過
IDHACK:針對_id進行查詢
SHARDING_FILTER:經過mongos對分片數據進行查詢
COUNT:利用db.coll.count()之類進行count運算
COUNTSCAN:count不使用用Index進行count時的stage返回
COUNT_SCAN:count使用了Index進行count時的stage返回
SUBPLA:未使用到索引的$or查詢的stage返回
TEXT:使用全文索引進行查詢時候的stage返回
附:explain查詢結果解析官方文檔:
https://docs.mongodb.org/v3.0/reference/explain-results/
數組上的索引
(1)能夠看得出在數組字段上創建索引的代價比較大,由於每次的刪除,更新都會對每個索引進行刷新,太消耗服務器的資源;
(2)能夠針對數組字段中的某一個元素作具體的單獨索引,減小索引的數量;
db.user.ensureIndex({"tags.0.music":1})
多鍵索引
若是在數組字段上建立索引,那麼這個索引稱爲多鍵索引( multikey)。
多鍵索引用explain函數中能夠看到「isMultikey」字段的值爲true,多鍵索引比非多鍵索引要慢一些;
db.user.ensureIndex({"address.province":1,"address.city":1,"address.pincode":1})
利用這種方式能夠創建任意深度的索引,例如能夠在X.Y.Z.A.B.C上創建索引。
可是,針對子文檔「address」上創建的索引,和創建在子文檔的某個字段「address.provincey」上的索引是不一樣的:
(1)對整個子文檔上創建的索引,只會提升整個子文檔的的查詢速度;
(2)只有查詢address.province字段,索引address.province纔會起做用,
其餘狀況索引address.province不起做用;
db.user.find({"address.province":"HeNan"})
db.user.find({"address.province":"HeNan","address.city":"ZhengZhou"})
db.user.find({"address.province":"HeNan","address.city":"ZhengZhou","address.pincode":"123"})
查詢分析
/* 1 */
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "mongotest.user",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"address.city" : {
"$eq" : "ZhengZhou"
}
},
{
"address.pincode" : {
"$eq" : "123"
}
},
{
"address.province" : {
"$eq" : "HeNan"
}
}
]
},
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"address.province" : 1.0,
"address.city" : 1.0,
"address.pincode" : 1.0
},
"indexName" : "address.province_1_address.city_1_address.pincode_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"address.province" : [],
"address.city" : [],
"address.pincode" : []
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"address.province" : [
"[\"HeNan\", \"HeNan\"]"
],
"address.city" : [
"[\"ZhengZhou\", \"ZhengZhou\"]"
],
"address.pincode" : [
"[\"123\", \"123\"]"
]
}
}
},
"rejectedPlans" : []
},
"serverInfo" : {
"host" : "kf-PC",
"port" : 27017,
"version" : "3.4.9",
"gitVersion" : "876ebee8c7dd0e2d992f36a848ff4dc50ee6603e"
},
"ok" : 1.0
}
參考來源: http://www.runoob.com/mongodb/mongodb-advanced-indexing.htmlmongodb