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_" } ]