MongoDB:16-MongoDB-索引数组字段和索引子文档字段

本文涉及的产品
云数据库 MongoDB,通用型 2核4GB
简介: 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()
  2. 执行结果
  3. /* 1 */
  4. {
  5.    "queryPlanner" : {
  6.        "plannerVersion" : 1,
  7.        "namespace" : "mongotest.user",
  8.        "indexFilterSet" : false,
  9.        "parsedQuery" : {
  10.            "tags" : {
  11.                "$eq" : "music"
  12.            }
  13.        },
  14.        "winningPlan" : {
  15.            "stage" : "FETCH",
  16.            "inputStage" : {
  17.                "stage" : "IXSCAN",
  18.                "keyPattern" : {
  19.                    "tags" : 1.0
  20.                },
  21.                "indexName" : "tags_1",
  22.                "isMultiKey" : true,
  23.                "multiKeyPaths" : {
  24.                    "tags" : [
  25.                        "tags"
  26.                    ]
  27.                },
  28.                "isUnique" : false,
  29.                "isSparse" : false,
  30.                "isPartial" : false,
  31.                "indexVersion" : 2,
  32.                "direction" : "forward",
  33.                "indexBounds" : {
  34.                    "tags" : [
  35.                        "[\"music\", \"music\"]"
  36.                    ]
  37.                }
  38.            }
  39.        },
  40.        "rejectedPlans" : []
  41.    },
  42.    "serverInfo" : {
  43.        "host" : "kf-PC",
  44.        "port" : 27017,
  45.        "version" : "3.4.9",
  46.        "gitVersion" : "876ebee8c7dd0e2d992f36a848ff4dc50ee6603e"
  47.    },
  48.    "ok" : 1.0
  49. }



  • 以上命令执行结果中会显示 "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. COUNTSCAN:count不使用用Index进行count时的stage返回
  15. COUNT_SCAN:count使用了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)可以针对数组字段中的某一个元素做具体的单独索引,减少索引的数量;
  • 例如,在数组字段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})
  2. 利用这种方式可以建立任意深度的索引,例如可以在X.Y.Z.A.B.C上建立索引。
  3. 但是,针对子文档“address”上建立的索引,和建立在子文档的某个字段“address.provincey”上的索引是不同的:
  4. 1)对整个子文档上建立的索引,只会提高整个子文档的的查询速度;
  5.     也就是说只有在完全匹配子文档的查询(包括字段顺序),子文档索引才会起作用;
  6. 2)只有查询address.province字段,索引address.province才会起作用,
  7.     其他情况索引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"})
  2. 查询分析
  3. /* 1 */
  4. {
  5.    "queryPlanner" : {
  6.        "plannerVersion" : 1,
  7.        "namespace" : "mongotest.user",
  8.        "indexFilterSet" : false,
  9.        "parsedQuery" : {
  10.            "$and" : [
  11.                {
  12.                    "address.city" : {
  13.                        "$eq" : "ZhengZhou"
  14.                    }
  15.                },
  16.                {
  17.                    "address.pincode" : {
  18.                        "$eq" : "123"
  19.                    }
  20.                },
  21.                {
  22.                    "address.province" : {
  23.                        "$eq" : "HeNan"
  24.                    }
  25.                }
  26.            ]
  27.        },
  28.        "winningPlan" : {
  29.            "stage" : "FETCH",
  30.            "inputStage" : {
  31.                "stage" : "IXSCAN",
  32.                "keyPattern" : {
  33.                    "address.province" : 1.0,
  34.                    "address.city" : 1.0,
  35.                    "address.pincode" : 1.0
  36.                },
  37.                "indexName" : "address.province_1_address.city_1_address.pincode_1",
  38.                "isMultiKey" : false,
  39.                "multiKeyPaths" : {
  40.                    "address.province" : [],
  41.                    "address.city" : [],
  42.                    "address.pincode" : []
  43.                },
  44.                "isUnique" : false,
  45.                "isSparse" : false,
  46.                "isPartial" : false,
  47.                "indexVersion" : 2,
  48.                "direction" : "forward",
  49.                "indexBounds" : {
  50.                    "address.province" : [
  51.                        "[\"HeNan\", \"HeNan\"]"
  52.                    ],
  53.                    "address.city" : [
  54.                        "[\"ZhengZhou\", \"ZhengZhou\"]"
  55.                    ],
  56.                    "address.pincode" : [
  57.                        "[\"123\", \"123\"]"
  58.                    ]
  59.                }
  60.            }
  61.        },
  62.        "rejectedPlans" : []
  63.    },
  64.    "serverInfo" : {
  65.        "host" : "kf-PC",
  66.        "port" : 27017,
  67.        "version" : "3.4.9",
  68.        "gitVersion" : "876ebee8c7dd0e2d992f36a848ff4dc50ee6603e"
  69.    },
  70.    "ok" : 1.0
  71. }


参考来源: http://www.runoob.com/mongodb/mongodb-advanced-indexing.html

参考来源:http://281816327.blog.51cto.com/907015/1601473



相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。   相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
目录
相关文章
|
3月前
|
存储 NoSQL 关系型数据库
|
6月前
|
NoSQL MongoDB 索引
【最佳实践】MongoDB导入数据时重建索引
【最佳实践】MongoDB导入数据时重建索引
172 0
|
7月前
|
JSON NoSQL MongoDB
mongodb基本操作,增删改查,查询,索引,权限机制
mongodb基本操作,增删改查,查询,索引,权限机制
|
6月前
|
NoSQL MongoDB 索引
开心档-软件开发入门之MongoDB 覆盖索引查询
开心档-软件开发入门之MongoDB 覆盖索引查询
45 0
|
12天前
|
存储 JSON NoSQL
MongoDB的文档存储格式BSON和JSON的区别
MongoDB的文档存储格式BSON和JSON的区别
|
23天前
|
NoSQL MongoDB 索引
【MongoDB】MongoDB 覆盖索引
【4月更文挑战第3天】【MongoDB】MongoDB 覆盖索引
|
2月前
|
SQL NoSQL Java
文档型数据库MongoDB
文档型数据库MongoDB
|
3月前
|
存储 NoSQL 关系型数据库
4-MongoDB索引知识
MongoDB索引知识
|
3月前
|
存储 JSON NoSQL
【MongoDB】<文档型数据库>Windows&Liunx安装MongoDB(无错完整)
【1月更文挑战第26天】【MongoDB】<文档型数据库>Windows&Liunx安装MongoDB(无错完整)
|
3月前
|
NoSQL MongoDB 索引
【待完善】MongoDB - 使用索引
【待完善】MongoDB - 使用索引
30 0