MongoDB索引类型汇总分享
目录
- 单字段索引
- 在单个字段上创建升序索引
- 在嵌入式字段上创建索引
- 在内嵌文档上创建索引
- 复合索引
- 多键索引
- 文本索引
- 2dsphere索引
- 创建测试数据
- 添加2dsphere索引
- 利用2dsphere索引查询多边形里的点
- 利用2dsphere索引查询球体上定义的圆内的点
- 2d索引
- 哈希索引
- 单字段索引
- 复合索引
- 多键索引
- 文本索引
- 2dsphere索引
- 2d索引
- geoHaystack索引
- 哈希索引
单字段索引
在单个字段上创建升序索引
handong1:PRIMARY> db.test.getIndexes()[ {"v" : 2,"key" : {"_id" : 1},"name" : "_id_","ns" : "db6.test" }]
在字段id上添加升序索引
handong1:PRIMARY> db.test.createIndex({"id":1}){ "createdCollectionAutomatically" : false, "numIndexesBefore" : 1, "numIndexesAfter" : 2, "ok" : 1, "$clusterTime" : {"clusterTime" : Timestamp(1621322378, 1),"signature" : {"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),"keyId" : NumberLong(0)} }, "operationTime" : Timestamp(1621322378, 1)}
handong1:PRIMARY> db.test.getIndexes()[ {"v" : 2,"key" : {"_id" : 1},"name" : "_id_","ns" : "db6.test" }, {"v" : 2,"key" : {"id" : 1},"name" : "id_1","ns" : "db6.test" }]
handong1:PRIMARY> db.test.find({"id":100}){ "_id" : ObjectId("60a35d061f183b1d8f092114"), "id" : 100, "name" : "handong", "ziliao" : { "name" : "handong", "age" : 25, "hobby" : "mongodb" } }
上述查询可以使用新建的单字段索引。
在嵌入式字段上创建索引
handong1:PRIMARY> db.test.createIndex({"ziliao.name":1}){ "createdCollectionAutomatically" : false, "numIndexesBefore" : 2, "numIndexesAfter" : 3, "ok" : 1, "$clusterTime" : {"clusterTime" : Timestamp(1621323677, 2),"signature" : {"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),"keyId" : NumberLong(0)} }, "operationTime" : Timestamp(1621323677, 2)}
以下查询可以用的新建的索引。
db.test.find({"ziliao.name":"handong"})
在内嵌文档上创建索引
handong1:PRIMARY> db.test.createIndex({ziliao:1}){ "createdCollectionAutomatically" : false, "numIndexesBefore" : 3, "numIndexesAfter" : 4, "ok" : 1, "$clusterTime" : {"clusterTime" : Timestamp(1621324059, 2),"signature" : {"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),"keyId" : NumberLong(0)} }, "operationTime" : Timestamp(1621324059, 2)}
以下查询可以使用新建的索引。
db.test.find({ziliao:{ "name" : "handong", "age" : 25, "hobby" : "mongodb" }})
复合索引
创建复合索引
db.user.createIndex({"product_id":1,"type":-1})
以下查询可以用到新建的复合索引
db.user.find({"product_id":"e5a35cfc70364d2092b8f5d14b1a3217","type":0})
多键索引
基于一个数组创建索引,MongoDB会自动创建为多键索引,无需刻意指定。
多键索引也可以基于内嵌文档来创建。
多键索引的边界值的计算依赖于特定的规则。
查看文档:
handong1:PRIMARY> db.score.find(){ "_id" : ObjectId("60a32d7f1f183b1d8f0920ad"), "name" : "dandan", "age" : 30, "score" : [ { "english" : 90, "math" : 99, "physics" : 88 } ], "is_del" : false }{ "_id" : ObjectId("60a32d8b1f183b1d8f0920ae"), "name" : "dandan", "age" : 30, "score" : [ 99, 98, 97, 96 ], "is_del" : false }{ "_id" : ObjectId("60a32d9a1f183b1d8f0920af"), "name" : "dandan", "age" : 30, "score" : [ 100, 100, 100, 100 ], "is_del" : false }{ "_id" : ObjectId("60a32e8c1f183b1d8f0920b0"), "name" : "dandan", "age" : 30, "score" : [ { "english" : 70, "math" : 99, "physics" : 88 } ], "is_del" : false }{ "_id" : ObjectId("60a37b141f183b1d8f0aa751"), "name" : "dandan", "age" : 30, "score" : [ 96, 95 ] }{ "_id" : ObjectId("60a37b1d1f183b1d8f0aa752"), "name" : "dandan", "age" : 30, "score" : [ 96, 95, 94 ] }{ "_id" : ObjectId("60a37b221f183b1d8f0aa753"), "name" : "dandan", "age" : 30, "score" : [ 96, 95, 94, 93 ] }
创建score字段多键索引:
db.score.createIndex("score":1)
handong1:PRIMARY> db.score.find({"score":[ 96, 95 ]}){ "_id" : ObjectId("60a37b141f183b1d8f0aa751"), "name" : "dandan", "age" : 30, "score" : [ 96, 95 ] }
查看执行计划:
handong1:PRIMARY> db.score.find({"score":[ 96, 95 ]}).explain(){ "queryPlanner" : {"plannerVersion" : 1,"namespace" : "db6.score","indexFilterSet" : false,"parsedQuery" : {"score" : {"$eq" : [96,95]}},"queryHash" : "8D76FC59","planCacheKey" : "E2B03CA1","winningPlan" : {"stage" : "FETCH","filter" : {"score" : {"$eq" : [96,95]}},"inputStage" : {"stage" : "IXSCAN","keyPattern" : {"score" : 1},"indexName" : "score_1","isMultiKey" : true,"multiKeyPaths" : {"score" : ["score"]},"isUnique" : false,"isSparse" : false,"isPartial" : false,"indexVersion" : 2,"direction" : "forward","indexBounds" : {"score" : ["[96.0, 96.0]","[[ 96.0, 95.0 ], [ 96.0, 95.0 ]]"]}}},"rejectedPlans" : [ ] }, "serverInfo" : {"host" : "mongo3","port" : 27017,"version" : "4.2.12","gitVersion" : "5593fd8e33b60c75802edab304e23998fa0ce8a5" }, "ok" : 1, "$clusterTime" : {"clusterTime" : Timestamp(1621326912, 1),"signature" : {"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),"keyId" : NumberLong(0)} }, "operationTime" : Timestamp(1621326912, 1)}
可以看到已经使用了新建的多键索引。
文本索引
????为了支持对字符串内容的文本搜索查询,MongoDB提供了文本索引。文本(text )索引可以包含任何值为字符串或字符串元素数组的字段
db.user.createIndex({"sku_attributes":"text"})
db.user.find({$text:{$search:"测试"}})
查看执行计划:
handong1:PRIMARY> db.user.find({$text:{$search:"测试"}}).explain(){ "queryPlanner" : {"plannerVersion" : 1,"namespace" : "db6.user","indexFilterSet" : false,"parsedQuery" : {"$text" : {"$search" : "测试","$language" : "english","$caseSensitive" : false,"$diacriticSensitive" : false}},"queryHash" : "83098EE1","planCacheKey" : "7E2D582B","winningPlan" : {"stage" : "TEXT","indexPrefix" : {},"indexName" : "sku_attributes_text","parsedTextQuery" : {"terms" : ["测试"],"negatedTerms" : [ ],"phrases" : [ ],"negatedPhrases" : [ ]},"textIndexVersion" : 3,"inputStage" : {"stage" : "TEXT_MATCH","inputStage" : {"stage" : "FETCH","inputStage" : {"stage" : "OR","inputStage" : {"stage" : "IXSCAN","keyPattern" : {"_fts" : "text","_ftsx" : 1},"indexName" : "sku_attributes_text","isMultiKey" : true,"isUnique" : false,"isSparse" : false,"isPartial" : false,"indexVersion" : 2,"direction" : "backward","indexBounds" : {}}}}}},"rejectedPlans" : [ ] }, "serverInfo" : {"host" : "mongo3","port" : 27017,"version" : "4.2.12","gitVersion" : "5593fd8e33b60c75802edab304e23998fa0ce8a5" }, "ok" : 1, "$clusterTime" : {"clusterTime" : Timestamp(1621328543, 1),"signature" : {"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),"keyId" : NumberLong(0)} }, "operationTime" : Timestamp(1621328543, 1)}
可以看到通过文本索引可以查到包含测试关键字的数据。
**注意:**可以根据自己需要创建复合文本索引。
2dsphere索引
创建测试数据
db.places.insert({loc : { type: "Point", coordinates: [ 116.291226, 39.981198 ] },name: "火器营桥",category : "火器营桥"})db.places.insert({loc : { type: "Point", coordinates: [ 116.281452, 39.914226 ] },name: "五棵松",category : "五棵松"})db.places.insert({loc : { type: "Point", coordinates: [ 116.378038, 39.851467 ] },name: "角门西",category : "角门西"})db.places.insert({loc : { type: "Point", coordinates: [ 116.467833, 39.881581 ] },name: "潘家园",category : "潘家园"})db.places.insert({loc : { type: "Point", coordinates: [ 116.468264, 39.914766 ] },name: "国贸",category : "国贸"})db.places.insert({loc : { type: "Point", coordinates: [ 116.46618, 39.960213 ] },name: "三元桥",category : "三元桥"})db.places.insert({loc : { type: "Point", coordinates: [ 116.400064, 40.007827 ] },name: "奥林匹克森林公园",category : "奥林匹克森林公园"})
添加2dsphere索引
db.places.createIndex( { loc : "2dsphere" } )
db.places.createIndex( { loc : "2dsphere" , category : -1, name: 1 } )
利用2dsphere索引查询多边形里的点
凤凰岭
[116.098234,40.110569]
天安门
[116.405239,39.913839]
四惠桥
[116.494351,39.912068]
望京
[116.494494,40.004594]
handong1:PRIMARY> db.places.find( { loc :...{ $geoWithin :...{ $geometry :...{ type : "Polygon" ,...coordinates : [ [...[116.098234,40.110569] ,...[116.405239,39.913839] ,...[116.494351,39.912068] ,...[116.494494,40.004594] ,...[116.098234,40.110569]...] ]...} } } } ){ "_id" : ObjectId("60a4c950d4211a77d22bf7f8"), "loc" : { "type" : "Point", "coordinates" : [ 116.400064, 40.007827 ] }, "name" : "奥林匹克森林公园", "category" : "奥林匹克森林公园" }{ "_id" : ObjectId("60a4c94fd4211a77d22bf7f7"), "loc" : { "type" : "Point", "coordinates" : [ 116.46618, 39.960213 ] }, "name" : "三元桥", "category" : "三元桥" }{ "_id" : ObjectId("60a4c94fd4211a77d22bf7f6"), "loc" : { "type" : "Point", "coordinates" : [ 116.468264, 39.914766 ] }, "name" : "国贸", "category" : "国贸" }
可以看到把集合中包含在指定四边形里的点,全部列了出来。
利用2dsphere索引查询球体上定义的圆内的点
handong1:PRIMARY> db.places.find( { loc :...{ $geoWithin :...{ $centerSphere :...[ [ 116.439518, 39.954751 ] , 2/3963.2 ]...} } } ){ "_id" : ObjectId("60a4c94fd4211a77d22bf7f7"), "loc" : { "type" : "Point", "coordinates" : [ 116.46618, 39.960213 ] }, "name" : "三元桥", "category" : "三元桥" }
返回所有半径为经度 116.439518 E 和纬度 39.954751 N 的2英里内坐标。示例将2英里的距离转换为弧度,通过除以地球近似的赤道半径3963.2英里。
2d索引
在以下情况下使用2d索引:
- 您的数据库具有来自MongoDB 2.2或更早版本的旧版旧版坐标对。
- 您不打算将任何位置数据存储为GeoJSON对象。
哈希索引
要创建hashed索引,请指定 hashed 作为索引键的值,如下例所示:
handong1:PRIMARY> db.test.createIndex({"_id":"hashed"}){ "createdCollectionAutomatically" : false, "numIndexesBefore" : 4, "numIndexesAfter" : 5, "ok" : 1, "$clusterTime" : {"clusterTime" : Timestamp(1621419338, 1),"signature" : {"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),"keyId" : NumberLong(0)} }, "operationTime" : Timestamp(1621419338, 1)}
注意事项
- MongoDB支持任何单个字段的 hashed 索引。hashing函数折叠嵌入的文档并计算整个值的hash值,但不支持多键(即.数组)索引。
- 您不能创建具有hashed索引字段的复合索引,也不能在索引上指定唯一约束hashed;但是,您可以hashed在同一字段上创建索引和升序/降序(即非哈希)索引:MongoDB将对范围查询使用标量索引。
推荐阅读
- MongoDB常用数据类型分享
- MongoDB利用oplog恢复数据的方法
- 生产环境MySQL索引时效的排查过程
- 数据库|从头开始搞懂 MySQL(06)索引的选择
- 【类型挑战】实现|【类型挑战】实现 Pick,难度??
- MYSQL|MYSQL基础
- MySQL 常见索引类型介绍
- APP开发从0到1|前后端分离之上线MongoDB【宝塔+falsk+MongoDB】
- ELK日志保留7天-索引生命周期策略
- 三高Mysql - Mysql索引和查询优化(偏理论部分)