MongoDB09-索引

  • MongoDB的索引用于查询(find、findOne)和排序。
    • 如果倾向于在集合中大量使用排序,那么应该根据排序的需求添加索引。如果在一个没有索引的集合中对目标字段使用sort(),并且数据量超过内部排序缓冲的最大大小,就会看到错误消息。
  • 在集合中添加索引后,MongoDB必须维护它们,并在每次执行写操作(例如更新、插入,或删除)时对它们进行更新。如果在集合中有过多的索引,它们有可能会对写操作的性能造成负面影响。
  • 索引最好用在读操作多的集合中。写入频繁的集合(例如日志系统),引入索引可能会减少每秒写入的文档数量峰值(这些文档可能会大量涌入集合中)。
  • 每个集合中最多有64个索引

1、查看索引

  • getIndexes函数会显示指定集合中的索引。显示所有索引,包括它们引用的字段或元素,以及在索引上设置的任何选项。
  • getIndexes函数的基本语法格式如下
db.collection.getIndexes()
  • 当在某个元素上定义索引时,MongoDB将构造一个二叉树索引,并用它高效地定位文档。如果未找到合适的索引,MongoDB将扫描集合中的所有文档,搜索满足查询的记录。

示例:

  • people集合没有任何用户自定义的索引,但MongoDB自动为这个集合的_id字段创建了索引。不需要做任何操作来创建或删除_id_索引,MongoDB将在集合创建时创建该索引,在集合删除时删除该索引
> db.people.getIndexes()
[ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_" } ]

2、创建索引

  • createIndex函数的基本语法格式如下
    • 首先将检查目前集合中是否已经创建了该索引。如果是,那么createlndex()只是返回该索引。
//在集合上创建索引
db.collection.createIndex(keys, options, commitQuorum)

//在集合上创建一个或多个索引
db.collection.createIndexes( [ keyPatterns ], options, commitQuorum )
  • createIndex函数的参数:
    • keys:包含字段和值的文档,其中字段是索引键,值是该字段的索引类型。对于字段的升序索引值是1; 对于降序索引,值是-1。从3.6开始,不能指定*为索引名称。
    • options:可选的。包含一组控制创建索引的选项的文档
    • commitQuorum:可选的。提交法定人数
  • options可用参数有:
//可用于所有索引类型的option
background: boolean,可选的。在MongoDB 4.2中已弃用。"background: true"指示MongoDB在后台构建索引。默认值为false。
unique:	boolean,可选的。是否创建唯一索引。若为true,则创建唯一索引。默认值为false。
name: string,可选的。索引的名称。如果未指定,MongoDB通过连接索引字段的名称和排序顺序来生成索引名。
partialFilterExpression: document,可选的。如果指定,索引只引用匹配筛选器表达式的文档。
sparse: boolean,可选的。如果为true,则索引只引用具有指定字段的文档。默认值为false。
expireAfterSeconds: integer,可选的。指定一个值(以秒为单位)作为TTL,以控制MongoDB在这个集合中保留文档的时间。
hidden: boolean,可选的。用于确定是否对查询计划器隐藏索引。
storageEngine: document,可选的。在创建索引时指定存储引擎。
//可用于排序的option
collation: {               //可选的。指定索引的排序规则。
   locale: <string>,
   caseLevel: <boolean>,
   caseFirst: <string>,
   strength: <int>,
   numericOrdering: <boolean>,
   alternate: <string>,
   maxVariable: <string>,
   backwards: <boolean>
}
//文本(text)索引选项
weights: document,可选的。对于文本索引,是包含字段和权重对的文档。权重是1到99,999之间的整数,表示该字段相对于其他索引字段的重要性。可以为部分或所有索引字段指定权重。参见使用权重控制搜索结果来调整分数。缺省值为1。
default_language: string,可选的。对于文本索引,确定停止词列表以及词干分析器和标记分析器的规则的语言。
language_override: string,可选的。对于文本索引,是集合文档中包含文档的覆盖语言的字段的名称。默认值为language。
textIndexVersion: integer,可选的。文本索引版本号。用户可以使用此选项覆盖默认版本号。

2.1、创建简单索引

  • 使用嵌入式文档中的字段,可使用普通的点标记寻址模式。
  • 如果指定的文档字段是数组类型,那么该索引将把数组中的所有元素作为不同的索引条目添加到其中。这称为多键索引,每个文档都将被链接到索引中的多个值。使用检查explain()就会看到其中提到了多值索引。

示例:

  • 创建升序或降序索引。
//插入数据
db.media.insert({"Type":"CD", "Artist":"Nirvana", "Title":"Nevermind", "Genre":"Grunge", "Releasedate":"1991.09.24", "Tracklist":[{"Track":"1", "Title":"You Know You're Right", "Length":"3:38"}, {"Track":"5", "Title":"Smells Like Teen Spirit", "Length":"5:02"}]})
db.media.insert({"Type":"Book", "Title":"Definitive Guideto MongoDB 3rd ed.", "ISBN":"978-1-4842-1183-0", "Publisher":"Apress", "Author":["Hows, David", "Plugge, Eelco", "Membrey, Peter", "Hawkins, Tim"]})

//在Type字段上创建一个简单的升序二叉树索引
> db.media.createIndex({"Type": 1})
//在Tracklist.Title字段上创建一个简单的降序二叉树索引
> db.media.createIndex({"Tracklist.Title": 1})

//查看索引
> 
> db.media.getIndexes()
[
	{
		"v" : 2,
		"key" : {
			"_id" : 1
		},
		"name" : "_id_"
	},
	{
		"v" : 2,
		"key" : {
			"Type" : 1
		},
		"name" : "Type_1"
	},
	{
		"v" : 2,
		"key" : {
			"Tracklist.Title" : 1
		},
		"name" : "Tracklist.Title_1"
	}
]

2.2、创建复合索引

  • 为查询中所有用到的字段都分别创建索引(即为每个字段都创建一个索引)。这种方式可能会加快查询的速度,但会降低添加和删除数据的速度,因为在每次执行修改操作时都要更新这些索引。
  • 查询过程只会使用一个索引,所以添加许多小索引通常并不会改善查询性能。
  • 复合索引提供了一种减少集合中索引数目的方法,它允许将多个字段结合在一起创建个索引,所以应该尽量使用复合索引
  • 复合索引有两种:子文档索引和手动定义的复合索引。
  • 可以在查询时不使用所有复合索引键的情况下使用复合索引。因此,可以构造出一组复合索引,覆盖到所有希望在集合中执行的查询,而不需要单独索引每个字段(从而避免对插入/更新操作的性能造成负面影响)。
  • 复合索引在使用索引进行排序时就没那么有用了。排序并不善于利用复合索引,除非数据项的列表和排序与索引结构匹配。

1、创建简单复合索引

  • 使用子文档中的字段作为索引键时,构建多键索引的字段顺序,要与它们在子文档中的顺序相同。许多情况下,这种方式都无法对创建索引的过程进行充分控制。
    • 为解决这个限制,并保证查询使用以目标方式构建的索引,需要查询的文档结构与创建索引所使用的子文档结构相同。
    • 还可为所有用于创建复合索引的字段显式命名,然后指定这些字段的结合顺序。

示例1:

//插入数据
db.media.insert({"Type":"Book", "Title":"Definitive Guideto MongoDB 3rd ed.", "ISBN":"978-1-4842-1183-0", "Publisher":"Apress", "Author":["Hows, David", "Plugge, Eelco", "Membrey, Peter", "Hawkins, Tim"]})
db.media.insert({"Type":"CD", "Artist":"Nirvana", "Title":"Nevermind", "Genre":"Grunge", "Releasedate":"1991.09.24", "Tracklist":[{"Track":"1", "Title":"You Know You're Right", "Length":"3:38"}, {"Track":"5", "Title":"Smells Like Teen Spirit", "Length":"5:02"}]})

//创建复合索引
> db.media.createIndex({"Tracklist.Track": 1, "Tracklist.Length": 1})

//使用符合索引
> db.media.find({"Tracklist.Track": "1", "Tracklist.Length":"3:38"}).explain('executionStats')

示例2:

//在orderDate字段(按升序)和zipcode字段(按降序)上创建复合索引。
db.collection.createIndex( { orderDate: 1, zipcode: -1 } )
//state字段(按升序)和zipcode字段(散列)上创建复合索引(从MongoDB 4.4开始,复合索引可以包含单个散列)
db.collection.createIndex( { "state" : 1, "zipcode" : "hashed" } )

2、MongoDB选择索引的方式

  • 优化器在为查询选择“最佳索引”时考虑的因素?
    • 最优索引必须包括查询的所有过滤字段和排序字段。
    • 查询中任何范围过滤字段排序字段必须在相等字段的后面(如果当前查询条件有多个最优索引,则MongoDB使用先前成功的计划,除非其执行性能不如另一个计划)。

示例:

//插入数据
db.student.insert({"id":1, "name": "hh1", "age": 22, "class": 3})
db.student.insert({"id":2, "name": "hh2", "age": 22, "class": 5})
db.student.insert({"id":3, "name": "hh3", "age": 23, "class": 1})
db.student.insert({"id":4, "name": "hh4", "age": 22, "class": 2})

//创建索引前执行查找
> db.student.find({id: {$gte: 2, $lte: 4}}).explain('executionStats')
	"executionStats" : {
		"executionSuccess" : true,
		"nReturned" : 3,              #符合查询条件的文档数
		"executionTimeMillis" : 0,    #查询计划选择和查询执行所需的总时间(以毫秒为单位)
		"totalKeysExamined" : 0,      #扫描的索引条目数
		"totalDocsExamined" : 4,      #在查询执行期间检查的文档数
...

//创建简单索引
> db.student.createIndex({"id": 1})
//执行查找
> db.student.find({id: {$gte: 2, $lte: 4}}).explain('executionStats')
	"executionStats" : {
		"executionSuccess" : true,
		"nReturned" : 3,
		"executionTimeMillis" : 0,
		"totalKeysExamined" : 3,
		"totalDocsExamined" : 3,
...
//执行查找,范围和相等查询
> db.student.find({id: {$gte: 2, $lte: 4}, age: 22}).explain('executionStats')
	"executionStats" : {
		"executionSuccess" : true,
		"nReturned" : 2,
		"executionTimeMillis" : 0,
		"totalKeysExamined" : 3,
		"totalDocsExamined" : 3,
...

//创建符合索引
> db.student.createIndex({"id": 1, "age": 1})
//执行查找
> db.student.find({id: {$gte: 2, $lte: 4}, age: 22}).explain('executionStats')
	"executionStats" : {
		"executionSuccess" : true,
		"nReturned" : 2,
		"executionTimeMillis" : 1,
		"totalKeysExamined" : 3,
		"totalDocsExamined" : 3,
...

//创建索引
> db.student.createIndex({"age": 1, "id": 1})
//执行查找
> db.student.find({id: {$gte: 2, $lte: 4}, age: 22}).explain('executionStats')
	"executionStats" : {
		"executionSuccess" : true,
		"nReturned" : 2,
		"executionTimeMillis" : 1,
		"totalKeysExamined" : 2,
		"totalDocsExamined" : 2,
...

3、创建复杂复合索引

  • 创建复合索引时,索引字段的顺序
    • (1)相等测试:按任意顺序把所有相等测试的字段添加到复合索引中。
    • (2)排序字段:在索引中添加排序字段,其顺序、方向和查询的排序相同。(只有存在多个排序字段,升序/降序才重要)
    • (3)范围过滤器:首先,为基数最低的字段添加范围过滤器(集合中不同的值最少),接着添加基数最低的范围过滤器,直到基数最高的范围过滤器为止。
  • 如果相等测试字段或范围过滤器字段没有过滤掉90%的文档,就可以省略它们,以减少索引的大小。
  • 如果集合上有几个索引,就可能需要提示Mongo使用正确的索引

2.3、在后台创建索引

db.collection.createIndex(keys, {background: true})
  • 使用createlndex()函数创建索引时,服务器必须读取集合中的所有数据并创建指定的索引。
    • 默认情况下,索引构建将在前台完成,集合所在数据库上的所有操作都将被阻塞,直至索引操作完成。
    • MongoDB因此引入了一个特性,它允许索引构建在后台执行。在后台构建索引的过程中,其他连接在数据库上的操作(读和写)并不会被阻塞。一旦索引创建完成,所有需要使用索引的查询都将立即使用它。值得注意的是,索引在后台构建时将耗费更长的时间。
  • 如果创建索引的操作已经挂起或者花费了太长时间,那么可以终止该操作。终止该操作后,已完成的部分索引也将被删除,防止数据库中出现损坏或无关的数据。
//查看目前MongoDB实例中运行的所有操作的列表(获取操作ID)
db.currentOp()
//通过操作ID终止操作
db.killOp(opid)

示例:

//插入数据
db.student.insert({"id":1, "name": "hh1", "age": 22, "class": 3})
db.student.insert({"id":2, "name": "hh2", "age": 22, "class": 5})
db.student.insert({"id":3, "name": "hh3", "age": 23, "class": 1})
db.student.insert({"id":4, "name": "hh4", "age": 22, "class": 2})

//在后台创建索引
> db.student.createIndex({"age": 1, "name": 1}, {background: true})

2.4、创建唯一键索引

db.collection.createIndex(keys, {unique: true})
  • 创建唯一键索引的字段的值必须唯一,即已有的该字段的值不能重复,插入新数据时会检查该字段的值是否唯一。如果不唯一,MongoDB将返回一个错误。
  • 如果某个文档在插入时缺少作为唯一键的字段,那么MongoDB将自动插入该字段并将值设置为null。这意味着,集合中只能插入一个缺少该键的文档,因为出现任何其他的null值都意味着该键不是唯一的。
  • 唯一键索引可以用于简单索引和复合索引,但不适用于多键值索引

示例:

//插入数据
db.student.insert({"id":1, "name": "hh1", "age": 22, "class": 3})
db.student.insert({"id":2, "name": "hh2", "age": 22, "class": 5})
db.student.insert({"id":3, "name": "hh3", "age": 23, "class": 1})
db.student.insert({"id":4, "name": "hh4", "age": 22, "class": 2})

//age字段的值不唯一,因此创建唯一索引失败
> db.student.createIndex({"age": 1}, {unique: true})
{
	"ok" : 0,
	"errmsg" : "Index build failed: ffcad366-8ed8-4621-ae16-f83167e536a0: Collection test.student ( 30f93a6e-1883-4914-892f-e6221331d265 ) :: caused by :: E11000 duplicate key error collection: test.student index: age_1 dup key: { age: 22.0 }",
	"code" : 11000,
	"codeName" : "DuplicateKey",
	"keyPattern" : {
		"age" : 1
	},
	"keyValue" : {
		"age" : 22
	}
}
//id字段的值唯一,因此创建唯一索引成功
> db.student.createIndex({"id": 1}, {unique: true})
{
	"numIndexesBefore" : 1,
	"numIndexesAfter" : 2,
	"createdCollectionAutomatically" : false,
	"ok" : 1
}

2.5、创建稀疏索引

db.collection.createIndex(keys, {sparse: true})
  • 稀疏索引:只为具有某个字段的文档创建索引(即只对部分文档进行索引)。
    • 例如,希望对邮件进行索引,但并不是所有邮件都有CC(carbon copy)或BCC(blind carbon copy)字段。如果在CC或BCC字段上创建非稀疏索引,那么所有文档都会被添加一个null值,因此可以考虑使用稀疏索引。
    • 它只对使用稀疏索引的查询有影响,因为对于某些文档,该查询可能并未进行检查。
  • 只对使用稀疏索引的查询有影响,因为对于某些文档,该查询可能并未进行检查。
  • 警告:如果在查找匹配查询的文档时,查询使用了稀疏索引,就可能没有找到所有匹配的文档,因为稀疏索引不会总是包含每个文档。

示例:

//插入数据
db.student.insert({"id":1, "name": "hh1", "age": 22, "class": 3})
db.student.insert({"id":2, "name": "hh2", "class": 5})
db.student.insert({"id":3, "name": "hh3", "age": 23, "class": 1})
db.student.insert({"id":4, "name": "hh4", "class": 2})

//创建稀疏索引
> db.student.createIndex({"age": 1}, {sparse: true})

2.6、创建部分索引

db.collection.createIndex(keys, {partialFilterExpression: document})
  • 从版本3.2开始,MongoDB可以创建部分索引。与稀疏索引一样,只包含匹配条件的文档。匹配条件(与find()的一样)来指定文档的范围。

示例:

//插入数据
db.student.insert({"id":1, "name": "hh1", "age": 22, "class": 3})
db.student.insert({"id":2, "name": "hh2", "age": 22, "class": 5})
db.student.insert({"id":3, "name": "hh3", "age": 23, "class": 1})
db.student.insert({"id":4, "name": "hh4", "age": 22, "class": 2})

//只给年龄小于22的创建索引
> db.student.createIndex({"name": 1}, {partialFilterExpression: {"age": {$lt: 23}}})

//查询时必须使用索引字段和一样的匹配条件才能命中索引
> db.student.find({name: "hh1", "age": {$lt: 23}}).explain('executionStats')
	"executionStats" : {
		"executionSuccess" : true,
		"nReturned" : 1,
		"executionTimeMillis" : 0,
		"totalKeysExamined" : 1,
		"totalDocsExamined" : 1,
...

2.7、创建TTL索引

db.collection.createIndex(keys, {expireAfterSeconds: integer})
  • 创建TTL索引,必须在单索引(非复合索引)中添加expireAfterSeconds标志和对应的秒数。表示索引字段值TTL小于当前服务器的时间,都将在下一次TTL删除任务执行时被删除。
  • 被索引的字段必须是BSON日期类型,否则将不会被删除。
  • TTL删除任务每60秒运行一次,因此旧文档在被删除之前可能有一些延迟。

示例:

  • (new Date(new Date().getTime()))是BSON日期类型的当前服务器时间
//插入数据,ts都不是BSON日期类型
db.student.insert({"id":1, "name": "hh1", "age": 22, "class": 3, "ts": "now"})
db.student.insert({"id":2, "name": "hh2", "age": 22, "class": 5, "ts": Date(new Date().getTime())})

//创建TTL索引,TTL是30秒
> db.student.createIndex({"ts": 1}, {expireAfterSeconds: 30})

//插入数据,ts都是BSON日期类型
db.student.insert({"id":3, "name": "hh3", "age": 23, "class": 1, "ts": (new Date(new Date().getTime()))})
//查看刚插入的数据
> db.student.find()
{ "_id" : ObjectId("632961d559c0cb6881ca01bb"), "id" : 1, "name" : "hh1", "age" : 22, "class" : 3, "ts" : "now" }
{ "_id" : ObjectId("632961d659c0cb6881ca01bc"), "id" : 2, "name" : "hh2", "age" : 22, "class" : 5, "ts" : "Tue Sep 20 2022 14:46:46 GMT+0800 (CST)" }
{ "_id" : ObjectId("6329620759c0cb6881ca01bd"), "id" : 3, "name" : "hh3", "age" : 23, "class" : 1, "ts" : ISODate("2022-09-20T06:47:35.667Z") }
//30秒后查看插入的数据(可能会有延迟)
> db.student.find()
{ "_id" : ObjectId("632961d559c0cb6881ca01bb"), "id" : 1, "name" : "hh1", "age" : 22, "class" : 3, "ts" : "now" }
{ "_id" : ObjectId("632961d659c0cb6881ca01bc"), "id" : 2, "name" : "hh2", "age" : 22, "class" : 5, "ts" : "Tue Sep 20 2022 14:46:46 GMT+0800 (CST)" }

2.8、创建文本索引

  • 创建文本索引的方式与创建其他索引的方式相同。例如,如果在文档的“key”字段上创建文本索引。
db.collection.createIndex({key: "text"}, {default_language: string})
  • MongoDB 2.4引入了文本索引。
  • 文本索引可以进行全文搜索。可以在一个大的文本块中搜索特定的单词或文本。例如,搜索博客文章正文的功能,在文档的一个字段(例如正文)或多个字段(例如正文和评论)中搜索单词或短语。
  • 文本搜索的工作方式是:首先创建文本索引,然后使用要查找的单词或文本进行全文搜索。
    • 文本索引将遍历集合中的所有文档,并分析出“文本字符串”(字段的值)中的“记号”(以空格等分隔符分割出来的字符串),接着MongoDB将取得每个“记号”的“词干”,然后找到该“记号”的“根词汇”。例如,将文本字符串分割后得到了记号fishing,然后解析出该记号的词干,得到根词汇fish,MongoDB将为该文档创建一个索引条目fish。
    • 对于用户用于搜索的文本,同样会进行记号和词干解析,然后MongoDB会将该参数与每个文档进行比较,并计算出相对得分,最后基于它们的得分将文档返回给用户。
  • 像the或it这样的单词如何抽取词干?对于非英语的文档又应该如何处理?答案是与它们类似的单词都不会被抽取词干,另外MongoDB的文本搜索引擎将支持许多种语言。
  • MongoDB的文本搜索引擎是由MongoDB公司的团队为文本数据处理而编写的自有引擎。MongoDB文本索引还利用了Snowball的字符串处理语言,该语言提供了对单词词干抽取终止词(这些单词都不会被抽取词干,因为它们并不代表索引或搜索中的任何有价值的概念)的支持。
  • 使用MongoDB文本索引时需要付出的代价
    • (1)文本索引非常大,并且可能增长非常迅速,这取决于所存储的文档数目以及每个被索引字段中的记号数目。
    • (2)基于现有文档构建文本索引非常耗时。
    • (3)在一个已经具有文本索引的字段中添加新的条目,代价就更加昂贵。
    • (4)文本索引在RAM中工作更好。
    • (5)由于文本索引的复杂性和大小,每个集合只能创建一个文本索引
  • 注意,MongoDB文本索引不区分大小写,这是执行文本查询时一个重要的考虑因素。
//插入数据
db.fish.insert({"num": 1, "body": "i like to go Fishing", "about": "recreation"})
db.fish.insert({"num": 2, "body": "i like hhfish", "about": "food"})
db.fish.insert({"num": 2, "body": "i like to go hhFishing", "about": "recreation"})
db.fish.insert({"num": 2, "body": "i like fish", "about": "food"})
db.fish.insert({"num": 2, "body": "i like cat", "about": "pet"})
db.fish.insert({"num": 2, "body": "i like dog", "about": "pet"})

2.8.1、创建简单文本索引

db.collection.createIndex({key: "text"})

示例:

//在body字段上创建文本索引
> db.fish.createIndex({body: "text"})

//查看文本索引
> db.fish.getIndexes()
[
	{
		"v" : 2,
		"key" : {
			"_id" : 1
		},
		"name" : "_id_"
	},
	{
		"v" : 2,
		"key" : {
			"_fts" : "text",
			"_ftsx" : 1
		},
		"name" : "body_text",
		"weights" : {
			"body" : 1
		},
		"default_language" : "english",
		"language_override" : "language",
		"textIndexVersion" : 3
	}
]

//使用文本索引
> db.fish.find({$text: {$search: "fish"}})
{ "_id" : ObjectId("6329874759c0cb6881ca01c7"), "num" : 2, "body" : "i like fish", "about" : "food" }
{ "_id" : ObjectId("6329874759c0cb6881ca01c4"), "num" : 1, "body" : "i like to go Fishing", "about" : "recreation" }
//使用{score: {$meta: "textScore"}}可以获得返回的文档的得分
> db.fish.find({$text: {$search: "fish"}}, {score: {$meta: "textScore"}})
{ "_id" : ObjectId("6329874759c0cb6881ca01c7"), "num" : 2, "body" : "i like fish", "about" : "food", "score" : 0.75 }
{ "_id" : ObjectId("6329874759c0cb6881ca01c4"), "num" : 1, "body" : "i like to go Fishing", "about" : "recreation", "score" : 0.6666666666666666 }
//过滤全文搜索
> db.fish.find({$text: {$search: "fish"}, about: "food"})
{ "_id" : ObjectId("6329874759c0cb6881ca01c7"), "num" : 2, "body" : "i like fish", "about" : "food" }

//使用$caseSensitive操作符区分大小写
> db.fish.find({$text: {$search: "fish", $caseSensitive: true}})
{ "_id" : ObjectId("6329949359c0cb6881ca01d3"), "num" : 2, "body" : "i like fish", "about" : "food" }

2.8.2、创建文本索引的复合索引

//使用多个字段创建文本索引的复合索引
db.collection.createIndex({key1: "text", key2: "text", ...})
//使用所有字段创建文本索引的复合索引
db.collection.createIndex({"$**": "text"})
  • 可以使用通配符"$**",引用所有文档的所有字段创建文本索引的复合索引,需要自定义一个索引名称,因为索引名称的最大长度是121个字符

示例:

//使用两个字段创建复合索引
> db.fish.createIndex({body: "text", about: "text"})

//使用所有字段创建复合索引,并自定义一个索引名称
> db.fish.createIndex({"$**": "text"}, {name: "text_name"})

//为索引中不同的字段指定权重,将会提高字段在索引结果中的重要性,比率为N:1(即没有指定的字段的权重为1)
> db.fish.createIndex({body: "text", about: "text"}, {weights: {body: 10, about: 5}})

//文本索引和普通文本索引结合创建复合索引(仅限于标准索引,即不能包含位置索引或数组字段上的索引)
> db.fish.createIndex({body: "text", about: 1})

2.8.3、文本索引中的语言

//指定spanish语言作为文本索引的语言
db.collection.createIndex({content: "text"}, {default_language: "spanish"})

//从文档中引用字段的值作为文本索引的语言
db.collection.createIndex({content: "text"}, {language_override: "lingvo"})
  • 创建文本索引时,默认使用语言的是english,但也可以显示指定其他语言。
  • 可以使用的语言有:
    • danish
    • dutch
    • english
    • finnish
    • french
    • german
    • hungarian
    • italian
    • norwegian
    • portuguese
    • romanian
    • russian
    • spanish
    • swedish
    • turkish
  • 如果在同一集合中存在多种语言,可以在所有文档都标记上正确的语言。MongoDB可以在文档中指定自己的语言,然后在创建索引时引用:
//lingvo字段指定了该文档的语言
{"_id": 1, "content": "cheese", "lingvo": "english"}
{"_id": 2, "content": "fromage", "lingvo": "french"}
{"_id": 3, "content": "queso", "lingvo": "spanish"}
{"_id": 4, "content": "ost", "lingvo": "swedish"}

//创建索引
db.quotes.createIndex({content: "text"}, {language_override: "lingvo"})

2.9、使用hint()指定索引

  • 使用索引查询文档时,MongoDB查询优化器将从备用索引中选择一个最佳索引用于查询。不过,有时查询优化器无法做出正确选择,因此可以使用hint()函数显示指定要使用的索引
//创建索引
db.media.createIndex({"Tracklist.Track": 1, "Tracklist.Length": 1})

//使用指定的索引
db.media.find({"Tracklist.Track": "1", "Tracklist.Length":"3:38"}).hint({"Tracklist.Track": 1, "Tracklist.Length": 1})

//不使用任何索引,即想要扫面集合的全不文档
db.media.find({"Tracklist.Track": "1", "Tracklist.Length":"3:38"}).hint({$natural: 1})

2.10、重建索引

db.collection.reIndex()
  • 如果怀疑集合中的索引已经损坏(查询后得到不一致的结果),那么可以强制重建受影响的索引。重建索引会删除集合上的所有索引并重新创建它们。

3、删除索引

  • dropIndex函数的基本语法格式如下
//从集合中删除指定的索引
db.collection.dropIndex(index)
//从集合中删除所有索引
db.collection.dropIndexes()

示例:

//插入数据
db.fish.insert({"num": 1, "body": "i like to go Fishing", "about": "recreation"})
db.fish.insert({"num": 2, "body": "i like fish", "about": "food"})

//创建索引
db.fish.createIndex({num: 1})
db.fish.createIndex({body: 1})
db.fish.createIndex({about: 1})

//使用索引名称删除指定的索引
> db.fish.dropIndex("num_1")
//使用创建索引时的规范删除指定的索引
> db.fish.dropIndex({body: 1})
//删除集合中的所有索引,除"_id_"索引外
> db.fish.dropIndexes()

//查看索引
> db.fish.getIndexes()
[ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_" } ]
posted @ 2022-09-20 00:51  麦恒  阅读(318)  评论(0编辑  收藏  举报