MongoDB开发深入之二:索引

索引分类:

  • 默认索引
  • 单一索引
  • 复合索引
  • 多键索引(数组索引)
  • 全文检索索引
  • 2dsphere 索引
  • 2D索引
  • ......


索引属性:

  • 到期TTL
  • 唯一索引
  • 部分索引
  • 稀疏索引

 

索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。特别在处理大量的数据时,查询甚至几分钟,这对网站的性能是非常致命的。

默认索引

默认情况下,所有集合都在_id 字段上有索引。

单一索引

一个名为records的集合,它包含类似于以下 sample 文档的文档:

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

以下操作在records集合的score字段上创建升序索引:

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

创建的索引将支持在字段score上选择的查询,如下所示:

db.records.find( { score: 2 } )
db.records.find( { score: { $gt: 10 } } )

一个名为records的集合,以下文档:

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

以下操作在location.state字段上创建索引:

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

创建的索引将支持在字段location.state上选择的查询,如下所示:

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

复合索引

一个名为products的集合,它包含类似于以下文档的文档:

{
 "_id": ObjectId(...),
 "item": "Banana",
 "category": ["food", "produce", "grocery"],
 "location": "4th Street Store",
 "stock": 4,
 "type": "cases"
}

以下操作在itemstock字段上创建升序索引:

db.products.createIndex( { "item": 1, "stock": 1 } )

索引将包含首先按item字段的值排序的文档的 references,并且在item字段的每个 value 内,按 stock 字段的值排序。

一个包含usernamedate字段的文档的集合events。 Applications 可以发出 return 结果首先按升序username值排序,然后降序(i.e.更近期到最后)date值的查询,例如:

db.events.find().sort( { username: 1, date: -1 } )

或者 return 结果首先按降序username值排序,然后按升序date值排序,例如:

db.events.find().sort( { username: -1, date: 1 } )

以下索引可以支持这两种排序操作:

db.events.createIndex( { "username" : 1, "date" : -1 } )

但是,上面的索引不能支持按升序username值排序,然后升序date值,如下所示:

db.events.find().sort( { username: 1, date: 1 } )

索引前缀

索引前缀是索引字段的起始子集。对于 example,请考虑以下复合索引:

{ "item": 1, "location": 1, "stock": 1 }

索引具有以下索引前缀:

  • { item: 1 }

  • { item: 1, location: 1 }

对于复合索引,MongoDB 可以使用索引来支持对索引前缀的查询。因此,MongoDB 可以在以下字段中使用索引进行查询:

  • item字段,

  • item字段和location字段,

  • item字段和location字段以及stock字段。

MongoDB 还可以使用索引来支持itemstock字段上的查询,因为item字段对应于前缀。但是,索引在支持查询时效率不高,因为只有itemstock的索引。

但是,MongoDB 无法使用索引来支持包含以下字段的查询,因为没有item字段,列出的字段中的任何一个都对应于前缀索引:

  • location字段,

  • stock字段,或

  • locationstock字段。

多键索引(数组索引)

MongoDB 会为 array 中的每个元素创建索引 key。这些多键索引支持对 array 字段的有效查询。可以在包含标量值(e.g .strings,numbers)和嵌套文档的数组上构建多键索引。

inventory集合:

{ _id: 5, type: "food", item: "aaa", ratings: [ 5, 8, 9 ] }
{ _id: 6, type: "food", item: "bbb", ratings: [ 5, 9 ] }
{ _id: 7, type: "food", item: "ccc", ratings: [ 9, 5, 8 ] }
{ _id: 8, type: "food", item: "ddd", ratings: [ 9, 5 ] }
{ _id: 9, type: "food", item: "eee", ratings: [ 5, 9, 5 ] }

该集合在ratings字段上有一个多键索引:

db.inventory.createIndex( { ratings: 1 } )

以下查询查找ratings字段为 array [ 5, 9 ]的文档:

db.inventory.find( { ratings: [ 5, 9 ] } )

MongoDB 可以使用多键索引查找ratings array 中任何位置5的文档。然后,MongoDB 为ratings array 等于查询 array [ 5, 9 ]的文档检索这些文档。

全文检索索引

MongoDB 提供文本索引以支持对 string 内容的文本全文搜索查询。 text索引可以包含 value 是 string 或 string 元素的 array 的任何字段。


2dsphere 索引

2dsphere索引支持计算 earth-like 球体上的几何的查询。 2dsphere index 支持所有 MongoDB 地理空间查询:包含,交集和邻近的查询。

以下操作在位置字段loc上创建索引:

db.places.createIndex( { loc : "2dsphere" } )

位置索引的查询:

  • GeoJSON Objects 由多边形限定
  • GeoJSON Objects 的交集
  • 靠近 GeoJSON 点
  • 球体上定义的圆内点

以下 example 选择完全存在于 GeoJSON 多边形内的所有点和形状:

db.places.find( { loc :
                  { $geoWithin :
                    { $geometry :
                      { type : "Polygon" ,
                        coordinates : [ [
                                          [ 0 , 0 ] ,
                                          [ 3 , 6 ] ,
                                          [ 6 , 1 ] ,
                                          [ 0 , 0 ]
                                        ] ]
                } } } } )

 

到期TTL

TTL 索引是 MongoDB 可用于在一定量时间(秒)之后自动从集合中删除文档的特殊单一索引。

数据到期对于某些类型的信息非常有用,例如机器生成的 event 数据,日志和 session 信息,这些信息只需要在数据库中持续有限的 time 时间。

要创建 TTL 索引,请在 value 为日期的字段或包含date 值的 array 的字段上使用db.collection.createIndex()方法和expireAfterSeconds选项。

例如,要在eventlog集合的lastModifiedDate字段上创建 TTL 索引,请在mongo shell 中使用以下操作:

db.eventlog.createIndex( { "lastModifiedDate": 1 }, { expireAfterSeconds: 3600 } )

限制

  • TTL 索引是 single-field 索引。 复合指数不支持 TTL 并忽略expireAfterSeconds选项。
  • _id字段不支持 TTL 索引。
  • 您无法在上限集合上创建 TTL 索引,因为 MongoDB 无法从上限集合中删除文档。
  • 您不能使用createIndex()更改现有索引的expireAfterSeconds的 value。而是将collMod database 命令与指数 collection flag 结合使用。否则,要更改现有索引选项的 value,必须先删除索引并重新创建。
  • 如果字段已存在 non-TTL single-field 索引,则无法在同一字段上创建 TTL 索引,因为您无法创建具有相同 key 规范且仅由选项不同的索引。要将 non-TTL single-field 索引更改为 TTL 索引,必须先删除索引并使用expireAfterSeconds选项重新创建。


唯一索引

唯一索引可确保索引字段不存储重复值; 

members集合的user_id字段上创建唯一索引:

db.members.createIndex( { "user_id": 1 }, { unique: true } )

部分索引

部分索引仅索引符合指定过滤器表达式的集合中的文档。通过索引集合中文档的子集,部分索引具有较低的存储要求,并降低了索引创建和维护的性能成本。

创建partial索引,请将db.collection.createIndex()方法与partialFilterExpression选项一起使用。 partialFilterExpression选项接受使用以下内容指定过滤条件的文档:

  • 等式表达式(value或使用$eq operator),
  • $exists:true表达,
  • $gt,$gte,$lt,$lte表达式,
  • $type表达式,
  • 只有 top-level 的$and operator

该索引仅索引rating字段大于 5 的文档。

db.restaurants.createIndex(
   { cuisine: 1, name: 1 },
   { partialFilterExpression: { rating: { $gt: 5 } } }
)

稀疏索引

稀疏索引仅包含具有索引字段的文档的条目,即使索引字段包含 null value 也是如此。索引会跳过缺少索引字段的任何文档。索引是“稀疏的”,因为它不包含集合的所有文档。相比之下,non-sparse 索引包含集合中的所有文档,为那些不包含索引字段的文档存储空值。

默认情况下稀疏的索引:
2 dsphere(version 2),2 d,geoHaystack和文本索引始终为稀疏索引。

以下操作会在addresses集合的xmpp_id字段上创建稀疏索引:

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

 

posted @ 2019-12-02 16:40  昕友软件开发  阅读(473)  评论(0编辑  收藏  举报
欢迎访问我的开源项目:xyIM企业即时通讯