1. 程式人生 > >MongoDB:16-MongoDB-索引陣列欄位和索引子文件欄位

MongoDB:16-MongoDB-索引陣列欄位和索引子文件欄位

  1. MongoDB允許深入文件內部,對巢狀欄位和陣列建立索引;
  2. 巢狀物件和陣列欄位可以和複合索引中的頂級欄位一起使用,多數情況下與“正常”索引欄位的行為也是一致的。
  3. 考慮以下文件集合(user ):

  1. db.user.insertMany(
  2. [
  3. {
  4. "address":{
  5. "province":"HeNan",
  6. "city":"ZhengZhou",
  7. "pincode":"123"
  8. },
  9. "tags":[
  10. "music",
  11. "cricket",
  12. "blogs"
  13. ],
  14. "name":"fly"
  15. },
  16. {
  17. "address":{
  18. "province":"HeBei",
  19. "city":"HanDan",
  20. "pincode"
    :"234"
  21. },
  22. "tags":[
  23. "music",
  24. "basket",
  25. "blogs"
  26. ],
  27. "name":"chen"
  28. },
  29. {
  30. "address":{
  31. "province":"ChongQing",
  32. "city":"ChongQing",
  33. "pincode":"456"
  34. },
  35. "tags":[
  36. "music",
  37. "writing",
  38. "running"
  39. ],
  40. "name":"wang"
  41. }
  42. ]
  43. )

以上文件包含了 address 子文件和 tags 陣列。

索引陣列欄位

  • 假設我們基於標籤來檢索使用者,為此我們需要對集合中的陣列 tags 建立索引。
  • 在陣列中建立索引,需要對陣列中的每個欄位依次建立索引
    。所以在我們為陣列 tags 建立索引時,會為 music、cricket、blogs三個值建立單獨的索引。

    • 使用以下命令建立陣列索引:
  1. db.user.ensureIndex({"tags":1})
    • 建立索引後,我們可以這樣檢索集合的 tags 欄位:
  1. db.user.find({tags:"music"})
    • 為了驗證我們使用使用了索引,可以使用 explain 命令:
  1. db.user.find({tags:"music"}).explain()
  1. 執行結果
  2. /* 1 */
  3. {
  4. "queryPlanner":{
  5. "plannerVersion":1,
  6. "namespace":"mongotest.user",
  7. "indexFilterSet":false,
  8. "parsedQuery":{
  9. "tags":{
  10. "$eq":"music"
  11. }
  12. },
  13. "winningPlan":{
  14. "stage":"FETCH",
  15. "inputStage":{
  16. "stage":"IXSCAN",
  17. "keyPattern":{
  18. "tags":1.0
  19. },
  20. "indexName":"tags_1",
  21. "isMultiKey":true,
  22. "multiKeyPaths":{
  23. "tags":[
  24. "tags"
  25. ]
  26. },
  27. "isUnique":false,
  28. "isSparse":false,
  29. "isPartial":false,
  30. "indexVersion":2,
  31. "direction":"forward",
  32. "indexBounds":{
  33. "tags":[
  34. "[\"music\", \"music\"]"
  35. ]
  36. }
  37. }
  38. },
  39. "rejectedPlans":[]
  40. },
  41. "serverInfo":{
  42. "host":"kf-PC",
  43. "port":27017,
  44. "version":"3.4.9",
  45. "gitVersion":"876ebee8c7dd0e2d992f36a848ff4dc50ee6603e"
  46. },
  47. "ok":1.0
  48. }
  • 以上命令執行結果中會顯示 "stage":"FETCH",,則表示已經使用了索引。
    1. stage的型別的意義
    2. mongodb的文件中列出了前4種類型,還有一些沒有列出來,但是會比較常見,這裡一併解釋一下。
    3. COLLSCAN :全表掃描
    4. IXSCAN:索引掃描
    5. FETCH::根據索引去檢索指定document
    6. SHARD_MERGE:各個分片返回資料進行merge
    7. SORT:表明在記憶體中進行了排序(與前期版本的scanAndOrder:true一致)
    8. SORT_MERGE:表明在記憶體中進行了排序後再合併
    9. LIMIT:使用limit限制返回數
    10. SKIP:使用skip進行跳過
    11. IDHACK:針對_id進行查詢
    12. SHARDING_FILTER:通過mongos對分片資料進行查詢
    13. COUNT:利用db.coll.count()之類進行count運算
    14. COUNTSCANcount不使用用Index進行count時的stage返回
    15. COUNT_SCANcount使用了Index進行count時的stage返回
    16. SUBPLA:未使用到索引的$or查詢的stage返回
    17. TEXT:使用全文索引進行查詢時候的stage返回
    18. 附:explain查詢結果解析官方文件:
    19. https://docs.mongodb.org/v3.0/reference/explain-results/
  1. 陣列上的索引
  2. 1)可以看得出在陣列欄位上建立索引的代價比較大,因為每次的刪除,更新都會對每一個索引進行重新整理,太消耗伺服器的資源;
  3. 2可以針對陣列欄位中的某一個元素做具體的單獨索引,減少索引的數量;
  • 例如,在陣列欄位