MongoDB:16-MongoDB-索引數組字段和索引子文檔字段

 

 
  1. MongoDB容許深刻文檔內部,對嵌套字段和數組創建索引;
  2. 嵌套對象和數組字段能夠和複合索引中的頂級字段一塊兒使用,多數狀況下與「正常」索引字段的行爲也是一致的。
    1.  
    2.  
    1. 考慮如下文檔集合(user ):html

    2.  
 
  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 數組。git

索引數組字段

 

  • 假設咱們基於標籤來檢索用戶,爲此咱們須要對集合中的數組 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.  
    4. COLLSCAN :全表掃描
    5. IXSCAN:索引掃描
    6. FETCH::根據索引去檢索指定document
    7. SHARD_MERGE:各個分片返回數據進行merge
    8. SORT:代表在內存中進行了排序(與前期版本的scanAndOrder:true一致)
    9. SORT_MERGE:代表在內存中進行了排序後再合併
    10. LIMIT:使用limit限制返回數
    11. SKIP:使用skip進行跳過
    12. IDHACK:針對_id進行查詢
    13. SHARDING_FILTER:經過mongos對分片數據進行查詢
    14. COUNT:利用db.coll.count()之類進行count運算
    15. COUNTSCANcount不使用用Index進行count時的stage返回
    16. COUNT_SCANcount使用了Index進行count時的stage返回
    17. SUBPLA:未使用到索引的$or查詢的stage返回
    18. TEXT:使用全文索引進行查詢時候的stage返回
    19.  
    20. 附:explain查詢結果解析官方文檔:
    21. https://docs.mongodb.org/v3.0/reference/explain-results/
  • 具體參考:http://blog.csdn.net/fly910905/article/details/78184302
 
  1. 數組上的索引
  2. 1)能夠看得出在數組字段上創建索引的代價比較大,由於每次的刪除,更新都會對每個索引進行刷新,太消耗服務器的資源;
  3. 2能夠針對數組字段中的某一個元素作具體的單獨索引,減小索引的數量;
  • 例如,在數組字段tags中的第1個元素中的music上創建索引:
 
  1. db.user.ensureIndex({"tags.0.music":1})
  • 一樣,只有精確匹配tags.0.music查詢,上述索引纔會起到索引的做用。
 
  1. 多鍵索引
  2. 若是在數組字段上建立索引,那麼這個索引稱爲多鍵索引( multikey)。
  3. 多鍵索引用explain函數中能夠看到「isMultikey」字段的值爲true,多鍵索引比非多鍵索引要慢一些;

 

索引子文檔字段

 

  • 假設咱們須要經過city、state、pincode字段來檢索文檔,因爲這些字段是子文檔的字段,因此咱們須要對子文檔創建索引。
    • 爲子文檔的三個字段建立索引,命令以下:

 

 
  1. db.user.ensureIndex({"address.province":1,"address.city":1,"address.pincode":1})

 

 

 
  1. 利用這種方式能夠創建任意深度的索引,例如能夠在X.Y.Z.A.B.C上創建索引。
  2. 可是,針對子文檔「address」上創建的索引,和創建在子文檔的某個字段「address.provincey」上的索引是不一樣的:
  3. 1)對整個子文檔上創建的索引,只會提升整個子文檔的的查詢速度;
  4. 也就是說只有在徹底匹配子文檔的查詢(包括字段順序),子文檔索引纔會起做用;
  5. 2)只有查詢address.province字段,索引address.province纔會起做用,
  6. 其餘狀況索引address.province不起做用;

 

    • 一旦建立索引,咱們可使用子文檔的字段來檢索數據:
 
  1. db.user.find({"address.province":"HeNan"})

 

 

 

    • 記住查詢表達式必須遵循指定的索引的順序。因此上面建立的索引將支持如下查詢:
 
  1. db.user.find({"address.province":"HeNan","address.city":"ZhengZhou"})

 

 

    • 一樣支持如下查詢:

 

 

 
  1. db.user.find({"address.province":"HeNan","address.city":"ZhengZhou","address.pincode":"123"})
 
  1. 查詢分析
  2. /* 1 */
  3. {
  4. "queryPlanner" : {
  5. "plannerVersion" : 1,
  6. "namespace" : "mongotest.user",
  7. "indexFilterSet" : false,
  8. "parsedQuery" : {
  9. "$and" : [
  10. {
  11. "address.city" : {
  12. "$eq" : "ZhengZhou"
  13. }
  14. },
  15. {
  16. "address.pincode" : {
  17. "$eq" : "123"
  18. }
  19. },
  20. {
  21. "address.province" : {
  22. "$eq" : "HeNan"
  23. }
  24. }
  25. ]
  26. },
  27. "winningPlan" : {
  28. "stage" : "FETCH",
  29. "inputStage" : {
  30. "stage" : "IXSCAN",
  31. "keyPattern" : {
  32. "address.province" : 1.0,
  33. "address.city" : 1.0,
  34. "address.pincode" : 1.0
  35. },
  36. "indexName" : "address.province_1_address.city_1_address.pincode_1",
  37. "isMultiKey" : false,
  38. "multiKeyPaths" : {
  39. "address.province" : [],
  40. "address.city" : [],
  41. "address.pincode" : []
  42. },
  43. "isUnique" : false,
  44. "isSparse" : false,
  45. "isPartial" : false,
  46. "indexVersion" : 2,
  47. "direction" : "forward",
  48. "indexBounds" : {
  49. "address.province" : [
  50. "[\"HeNan\", \"HeNan\"]"
  51. ],
  52. "address.city" : [
  53. "[\"ZhengZhou\", \"ZhengZhou\"]"
  54. ],
  55. "address.pincode" : [
  56. "[\"123\", \"123\"]"
  57. ]
  58. }
  59. }
  60. },
  61. "rejectedPlans" : []
  62. },
  63. "serverInfo" : {
  64. "host" : "kf-PC",
  65. "port" : 27017,
  66. "version" : "3.4.9",
  67. "gitVersion" : "876ebee8c7dd0e2d992f36a848ff4dc50ee6603e"
  68. },
  69. "ok" : 1.0
  70. }

 

參考來源: http://www.runoob.com/mongodb/mongodb-advanced-indexing.htmlmongodb

參考來源:http://281816327.blog.51cto.com/907015/1601473數組

相關文章
相關標籤/搜索