众所周知,创建索引可以极大地提高查询效率,MongoDB作为一款nosql数据库,同样也支持通过索引进行查询的性能提升。倘若没有索引,MongoDB必须执行在整个集合中的扫描,从而找出匹配查询语句的文档。倘若对于某个查询有合适的索引存在,MongoDB可以使用索引限制必须检索文档的数量。
索引是一种极其特殊的数据结构,它以一种方便检索的形式存储了集合中数据集的一小部分。索引存储了指定字段或者指定字段集合的值,并通过字段的值进行排序。索引实体的排序支持高质量相等匹配和范围相关的查询操作。除此之外,MongoDB可以通过使用索引中的顺序返回排序结果。MongoDB提供了集合级别的索引创建和使用。
缺省的_id索引
MongoDB默认在集合创建的时候为_id字段创建了一个唯一索引。这么做是为了防止客户端插入多个_id有相同值得文档。并且该索引一经创建无法被销毁。
创建索引
在原生的Java驱动中,可以使用db.collection.crateIndex()方法创建索引。格式如下:
db.collection.createIndex( <key and index type specification>, <options> )该方法只有在key对应的type specification不存在的情况下才会创建索引。MongoDB的索引使用 B-tree 数据结构。 1.先来了解下<options>: 在官方的文档中,<options>是包含了控制索引创建的一系列选择的文档对象。 所有索引类型通用的<options>选项列表(3.0版本开始,dropDups这个选项不在可用):
参数 | 类型 | 参数描述 |
background | boolean | 可选参数,指定true表示在后台创建索引,不阻塞其他的数据库活动。默认值false。 |
unique | boolean | 可选参数,指定true表示创建唯一索引,集合将不会接受索引key(keys)与在索引中某个值可以匹配的文档的插入。缺省情况下是false。 |
name | string | 可选参数,索引的名称。在没有指定的情况下,MongoDB将会自动生成一个以索引key和排序方式(0或1)用下划线连接的索引名称。 指定索引名称时,其完整的命名空间(<database name>.<collection name>.$<index name>)不能超过128个字节。 |
partialFilterExpression | document | 可选参数。如果指定,该索引将会引用匹配该过滤表达式的文案当。 一个过滤表达式必须包含:
|
sparse | boolean | 可选参数,稀疏索引。指定true,索引将引用指定字段的文档。这样的索引有较少的空间开销,但是在不同的情景下表现不同,尤其是排序。默认是false。 |
expireAfterSeconds | integer | 可选参数,指定一个以秒为单位的值,这样可以控制文档在集合中的存在时间。 |
storageEngine | document | 可选的参数,3.0新增。格式 { <storage-engine-name>: <options> },指定存储引擎。 |
全文索引的选项:
参数 | 类型 | 参数描述 |
weights | document | 可选参数,包含filed、weight对的文档对象。weight是1~99999的的整形数,其值表示某个filed和其它索引filed的关联度及重要性。可以为部分或全部索引字段指定该值。默认值1.详细 |
default_language | string | 可选参数,默认是英语。language决定了禁用词列表和词干分析器和分词器的规则。 |
language_override | string | 可选参数,默认为language。在一个集合的某个文档的某个Filed,可以在创建索引的时候指定不同的语言。 |
textIndexVersion | integer | 可选参数,全文索引的版本。 |
2.索引的类型
MongoDB提供很多不同的索引类型支持特定类型的数据和查询。这里只讨论单一索引、复合索引、全文索引三类。
单一索引
除了MongoDB自定义的_id索引,数据库也支持用户在文档的单个Filed上自定义的递增、递减索引。单一索引支持在索引字段的查询,比如假设有一个集合records,其中的温昂结构如下:
{
"_id": ObjectId("570c04a4ad233577f97dc459"),
"score": 1034,
"location": { state: "NY", city: "New York" }
}
我们在score上创建递增索引:
db.records.createIndex( { score: 1 } )这样创建的索引支持在score字段上的查询,如:
db.records.find( { score: 2 } ) db.records.find( { score: { $gt: 10 } } )复合索引 即在在多个Filed创建的索引。在复合索引中的Filed的排序具有重要的意义。举个例子,如果一个复合索引由{ userid: 1, score: -1 }组成,索引首先将会按userid递增排序,在相同的userid中,再次按照score递减排序。另外,索引的key的排序直接决定了该索引支持的排序操作。举个例子;
假设有个集合events,它的文档包含username和date两个字段,创建如下索引:
db.events.createIndex( { "username" : 1, "date" : -1 } )如此,仅会支持如下两种查询排序的操作将会支持:
db.events.find().sort( { username: 1, date: -1 } ) db.events.find().sort( { username: -1, date: 1 } )然而,如下的操作将不会被支持:
db.events.find().sort( { username: 1, date: 1 } )需要注意的是:如果创建了一个符合索引,MongoDB可以使用索引支持在索引前缀上的查询。索引前缀是指创建索引的Filed列表从第一个Filed开始的子集,如创建如下形式的索引:
db.collection.crateIndex({ "item": 1, "location": 1, "stock": 1 });那么,该索引仅支持如下三种查询:
db.collection.find({ item: "item1", location: "location1", stock: "stock1" }); db.collection.find({ item: "item2", location: "location2"}); db.collection.find({ item: "item3"});
并且仅支持在这三个Filed中的一个或多个上的全递增和全递减排序操作。
全文索引
从MongoDB 3.2开始,MongoDB有了第三个版本的全文索引。MongoDB提供全文索引支持在一整行上的文本搜索。全文索引可以是值为String或者String数组的任何一个Filed。一个集合最多可以有一个全文索引。
创建全文索引:
创建全文索引,使用 db.collection.createIndex()方法。为了索引一个包含一个String 或者 String数组的Filed,指出这个FIIED并在索引文档中用“text”表示。如下:
db.reviews.createIndex( { comments: "text" } )
同样,可以在多个FIled上创建全文索引。如下在subject和comment上创建了一个全文索引:
db.reviews.createIndex( { subject: "text", comments: "text" } )
当需要删除一个全文索引时,用db.collection.dropIndex("MyTextIndex"),其中 MyTextIndex是索引的名称。
限定比重(Weights)
对于一个全文索引,一个索引字段的比重表明某个字段与其他字段关联的重要意义。在文档中的每个索引Filed,