MongoDB的索引(二)

太阳2年前技术文章486


四、Case Insesitive索引

1、语法

db.collection.createIndex( 
{ "key" : 1 },
{ collation: {locale : <locale>,strength : <strength>}} )

collation:指定语言规则

strength:指定比较规则(是否区分大小写),1-5,数组越大,比较规则越严格,默认等级为3

2、使用case insensitive索引不影响查询结果,但是会增加查询的资源消耗

3、当创建索引时候指定了locale和strength,需要在查询时候指定相同的locale和strength才能确保有效使用索引。

1)示例集合

> db.fruit.find()
{ "_id" : ObjectId("5d2af3815e1bc81c62ef58b6"), "type" : "apple" }
{ "_id" : ObjectId("5d2af3815e1bc81c62ef58b7"), "type" : "Apple" }
{ "_id" : ObjectId("5d2af3815e1bc81c62ef58b8"), "type" : "APPLE" }
db.fruit.createIndex( { type: 1},
{ collation: { locale: 'en', strength: 2 } } )

2)查询结果

1.没有指定locale和strength,无法使用索引,查询记录为1
db.fruit.find( { type: "apple" } ) 

2.指定索引对应的locale和strength,使用索引,查询记录为2
db.fruit.find( { type: "apple" } ).collation( { locale: 'en', strength: 2 } )

3.指定非索引对应的locale和strength,不使用索引,返回记录为1
db.fruit.find( { type: "apple" } ).collation( { locale: 'en', strength: 1 } )

4、当创建集合时指定了locale和strength,集合的索引和查询默认使用对应的locale和strength。

1)示例集合

> db.createCollection("names", { collation: { locale: 'en_US', strength: 2 } } )
> db.names.createIndex( { first_name: 1 } ) // inherits the default collation
> db.names.find()
{ "_id" : ObjectId("5d3023b1cd8afaa592e2398d"), "first_name" : "Betsy" }
{ "_id" : ObjectId("5d3023b1cd8afaa592e2398e"), "first_name" : "BETSY" }
{ "_id" : ObjectId("5d3023b1cd8afaa592e2398f"), "first_name" : "betsy" }

2)查询结果

1.使用集合默认locale和strength,返回记录为3
db.names.find( { first_name: "betsy" } )

2.无法使用索引且只返回一条记录,因为strength默认为3
db.names.find( { first_name: "betsy" } ).collation( { locale: 'en_US' } )



五、Sparse索引

1、语法

db.addresses.createIndex( { "xmpp_id": 1 }, { sparse: true } )

2、稀疏索引的索引仅仅会覆盖包含索引字段的文档,所以根据稀疏索引来统计文档数/查询/排序时,可能得到的计算往往不是准确的

1)示例集合

> db.collection.find()
{ "_id" : 1, "y" : 1 }
{ "_id" : 2, "x" : 1, "y" : 2 }
{ "_id" : 3, "x" : 2 }

db.collection.createIndex( { x: 1 }, { sparse: true } );
db.collection.createIndex({ y: 1 });

2)查询结果

> db.collection.find().count();
3
> db.collection.find().hint({ y: 1 }).count();
3
> db.collection.find().hint( { x: 1 } ).count();        //仅统计x字段存在的记录
2

3、2dsphere (version 2)、 2d,、geoHaystack、text indexes都默认为稀疏索引

4、2dsphere和text都可以创建为稀疏复合索引,这些稀疏复合索引是否存在仅仅依赖于geospatial/text索引字段

5、稀疏索引的查询

1)示例文档

> db.scores.find()
{ "_id" : ObjectId("523b6e32fb408eea0eec2647"), "userid" : "newbie" }
{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }
{ "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 }
> db.scores.createIndex( { score: 1 } , { sparse: true } )

2)查询结果

#查询结果不会包含无score字段记录
> db.scores.find( { score: { $lt: 90 } } )
{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }

6、稀疏索引的排序

1)示例文档

> db.scores.find()
{ "_id" : ObjectId("523b6e32fb408eea0eec2647"), "userid" : "newbie" }
{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }
{ "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 }
> db.scores.createIndex( { score: 1 } , { sparse: true } )

2)查询结果

#COLLSCAN,未使用索引
> db.scores.find().sort( { score: -1 } )
{ "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 }
{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }
{ "_id" : ObjectId("523b6e32fb408eea0eec2647"), "userid" : "newbie" }

#强制使用稀疏索引后,得到记录只有2条
> db.scores.find().sort( { score: -1 } ).hint( { score: 1 } )
{ "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 }
{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }

7、稀疏索引 + 唯一索引,仅仅限制满足稀疏索引字段唯一,不包含稀疏索引字段的文档可重复

1)示例集合

db.scores.createIndex( { score: 1 } , { sparse: true, unique: true } )
> db.scores.find()
{ "_id" : ObjectId("523b6e32fb408eea0eec2647"), "userid" : "newbie" }
{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }
{ "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 }

2)查询结果

> db.scores.insert( { "userid": "AAAAAAA", "score": 43 } )
WriteResult({ "nInserted" : 1 })
> db.scores.insert( { "userid": "BBBBBBB", "score": 34 } )
WriteResult({ "nInserted" : 1 })
> db.scores.insert( { "userid": "CCCCCCC" } )
WriteResult({ "nInserted" : 1 })
> db.scores.insert( { "userid": "DDDDDDD" } )
WriteResult({ "nInserted" : 1 })
>
> db.scores.insert( { "userid": "AAAAAAA", "score": 82 } )
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" : "E11000 duplicate key error collection: test.scores index: score_1 dup key: { : 82.0 }"
}
})
> db.scores.insert( { "userid": "BBBBBBB", "score": 90 } )
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" : "E11000 duplicate key error collection: test.scores index: score_1 dup key: { : 90.0 }"
}
})



六、Single Field Indexes

{
  "_id": ObjectId("570c04a4ad233577f97dc459"),
  "score": 1034,
  "location": { state: "NY", city: "New York" }
}

1、语法:

db.records.createIndex( { score: 1 } )

2、在嵌套字段上创建索引

db.records.createIndex( { "location.state": 1 } )

可支持查询:

db.records.find( { "location.state": "CA" } )
db.records.find( { "location.city": "Albany", "location.state": "NY" } )

3、在嵌套文档上创建索引

db.records.createIndex( { location: 1 } )

可支持查询:

db.records.find( { location: { city: "New York", state: "NY" } } )

需要注意的是:

对于以上查询,location嵌套字段的顺序与创建索引顺序不一致可以使用索引,但是查询结果记录为0,因为查询顺序

> db.records.find()
{ "_id" : ObjectId("570c04a4ad233577f97dc459"), "score" : 1034, "location" : { "state" : "NY", "city" : "New York" } }
>
> db.records.find( { location: { city: "New York", state: "NY" } } )
>
> db.records.find( { location: { state: "NY",city: "New York" } } )
{ "_id" : ObjectId("570c04a4ad233577f97dc459"), "score" : 1034, "location" : { "state" : "NY", "city" : "New York" } }


相关文章

oracle PUS.SPU.CPU.BP.RU.RUR概念简介

PUS.SPU.CPU.BP.RU.RUR概念介绍PSU(Patch Set Updates):Oracle 选取在每个季度用户下载数量最多,并且得到验证具有较低风险的补丁放入到每个季度的PSU中,修...

容器引擎Podman常用命令浅析

容器引擎Podman常用命令浅析

Podman简介Podman 是一个开源的无守护进程的容器引擎,用于在Linux系统上开发、管理和运行OCI容器。容器既可以以root身份运行,也可以在无root模式下运行。Podman 提供与 Do...

MySQL性能优化(四)隐式类型转换

我们知道, where条件中,对一个索引字段进行运算会导致无法使用该字段的索引。有些情况下,即使没有显式地对索引字段进行运算,但是数据库会进行隐式类型转换,这也会导致无法使用索引。会发生隐式类型转换的...

Kubernetes网络模型与CNI网络插件

Kubernetes网络模型与CNI网络插件

在 Flannel 的网络插件中,容器跨主机网络的两种实现方法:UDP 和 VXLAN。它们有一个共性,就是用户的容器都连接在 docker0 网桥上。而网络插件则在宿主机上创建了一个特殊的设备(UD...

Kubernetes源码解读(四)--Lister&Watcher源码分析

Kubernetes源码解读(四)--Lister&Watcher源码分析

Lister&&Watcher是Reflector的一个主要能力提供者,我们来看看Lister&&Watcher是如何实现List()和watch()的过程的。List...

数据库经验之谈-数据库join时必须使用索引

数据库join时必须使用索引,否则效率急剧下降。当执行数据库 JOIN 操作时,如果没有使用索引,则数据库需要执行全表扫描(Full Table Scan)来查找匹配的行。这意味着数据库将检查表中的每...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。