(目录)

MongoDB的索引分为单字段索引、复合索引、地理空间索引等,每个索引的创建时的参数不同,但重建、查询、删除索引的方法都一样

创建索引

语法

db.collection.createIndex() db.collection.createIndex(keys, options, commitQuorum

  • keys:用户设定索引的字段和排序规则。排序规则设为1,表示升序;设为-1,表示降序
  • options:可选参数。包括以下参数
    • backgroud: 创建索引是否会在后台进行,默认false
    • unique: 索引是否为唯一索引,默认false
    • name: 创建的索引名称
    • partialFilterExpression: 索引只适用于筛选条件匹配的文档
    • sparse: 索引只用于指定字段的文档
    • expireAfterSeconds: 用于TTL索引中,用来控制文档保留在集合中的时间
    • storageEngine: 索引使用的存储引擎
    • hidden: MongoDB4.4版本中新增的内人,可以指定索引是否隐藏

索引类型

单字段索引

只在一个字段上创建的索引 示例:在Product集合的Weight字段上创建一个单字段的升序索引 db.Product.createIndex({"Weight":1})

复合索引

将多个字段组合成一个索引。这个索引整体上按第一个字段进行排序,对于子一个字段相同的值,再按照第二个字段进行排序。 在创建符合索引时,字段的顺序非常重要,查询时,条件中必须包含索引的前缀字段 示例:在Product集合中,创建一个用Weight字段降序排列、用SysNo字段升序排列的索引 db.Product.createIndex({"Weight":-1,"SysNo":1})

TTL索引

TTL(time-to-live)索引是可以针对文档中的时间类型字段设定一个时间值。如果字段的时间超过设定值,则文档就会被自动删除。 TTL索引对于日志型或者需要定期删除数据的文档非常有用。 TTL索引的四个特点

  • TTL索引不可以是复合索引
  • 如果创建TTL索引的字段不是时间类型,则文档不会被删除
  • TTL索引每60s运行一次,移除过期的文档
  • 如果时间类型的字段已经被设定为其他索引,则无法通过TTL索引来删除文档

示例:在Carts集合中,文件需要在CreateDate字段时间的7天后删除,并以CreateDate字段进行降序排列 db.Carts.createIndex({"CreateDate":1},{expireAfterSeconds:60*24*7})

全文本索引

全文本索引主要用来冲寻MongoDB中的文本文档。索引可以包含一个或多个字段,在建立全本文索引时,需要将字段指定为文本索引text/

全文本索引的特点
  • MongoDB的写入速度会变慢
  • 一个集合最多只能创建一个全文本索引
  • 全文本索引查找时不区分大小写
  • 全文本索引可以选择索引所有字符串类型的字段或指定字段
  • 可以根据查找优先权来设定不同文本索引的权限
  • 目前不支持中文文本索引。通用语言包括:英语、法语、德语、俄语、西班牙语、土耳其语等
全文本索引的创建

全文索引可以索引所有字符串类型字段或指定字段 可以为不同的文本索引字段设置不同的权重,在查询时,从权重高的开始查询。权重的默认值为1,可以设定为1-99999之间的整数

# 在post集合的author和email字段上创建全文本索引
db.posts.createIndex({"author":"text","email":"text"})
# 将zips集合的所有字符串字段创建成全文本索引
db.zips.createIndex({"$**":"text"})
# 将inspections集合的所有字符串字段创建成全文本索引,优先查询certificate_number字段,然后查询result字段
db.inspections.createIndex({"$**":"text"},{"weights":{"certificate_number":10,"result":5}})
通过全文本索引进行查询
# 查询zips集合中包含"rose"的文档
db.zips.find({$text:{$search:"rose"}})

地理空间索引

MongoDB对于坐标数据的文档提供了地理空间索引,使用该索引,可以通过坐标快速的查询到对应的文档。

地理空间索引类型
  • 2dsphere:这种类型索引支持查询地球球体上的位置,支持“GeoJSON”和“传统坐标”类型的数据
    • GeoJSON数据:需要使用嵌入式文档,在其中可以使用coordinates字段来指定坐标位置,使用type字段指定坐标类型,坐标分为三种类型
      • 点(Point): coordinates只有一个坐标
      • 线(LineString): coordinates有两个坐标
      • 多边形(Polygon): coordinates有两个以上的坐标
    • 传统坐标数据:只需要一个字段来指定坐标的位置 无论是“GeoJSON”还是“传统坐标”类型,其中经纬度的存储方式必须是数组形式,即[经度,纬度],经度的有效值是-180-180,纬度的有效值是-90-90。如果经纬度的存储位置颠倒,或者没有介于这两组值之间。则在创建地理空间索引时MongoDB会自动报错
  • 2d:这种类型的索引支持查询二位平面上的位置,仅支持传统坐标类型的数据
地理空间索引的创建
# trips集合信息
db.trips.findOne()
{
        "_id" : ObjectId("572bb8222b288919b68abf5a"),
        "tripduration" : 379,
        "start station id" : 476,
        "start station name" : "E 31 St & 3 Ave",
        "end station id" : 498,
        "end station name" : "Broadway & W 32 St",
        "bikeid" : 17827,
        "usertype" : "Subscriber",
        "birth year" : 1969,
        "start station location" : {
                "type" : "Point",
                "coordinates" : [
                        -73.97966069,
                        40.74394314
                ]
        },
        "end station location" : {
                "type" : "Point",
                "coordinates" : [
                        -73.98808416,
                        40.74854862
                ]
        },
        "start time" : ISODate("2016-01-01T00:00:45Z"),
        "stop time" : ISODate("2016-01-01T00:07:04Z")
}
# 在start station location字段上创建2dsphere地理空间索引
db.trips.createIndex({"start station location":"2dsphere"})
# 在coordinates字段上创建2d地理空间索引
db.trips.createIndex({"coordinates":"2d"})
地理空间查询

使用$geoNear操作符可以把指定坐标到文档中坐标的距离由近到远的排列出来,并设定distanceField参数显示两者之间的距离。 从MongoDB4.0开始,使用$geoNear操作符并设定key参数,就可以查询集合中同时拥有2dsphere2d的地理空间索引的文档

# 查询
db.trips.aggregate([
    {
    $geoNear:{
        near:{ type:"Point",coordinates:[-73,40]}, # 使用2dsphere索引
        distanceField : "dist.location", # 计算指定坐标与文档中坐标的距离
        key : "start station location" }   #指定索引字段
    }       
])
# 结果
{ 
    "_id" : ObjectId("572bb8222b288919b68acf75"), 
    "tripduration" : 410, 
    "start station id" : 3043, 
    "start station name" : "Lewis Ave & Decatur St", 
    "end station id" : 437, 
    "end station name" : "Macon St & Nostrand Ave", 
    "bikeid" : 22644, 
    "usertype" : "Subscriber", 
    "birth year" : 1980, 
    "start station location" : { "type" : "Point", "coordinates" : [ -73.934903, 40.6814598 ] }, 
    "end station location" : { "type" : "Point", "coordinates" : [ -73.9500479759, 40.6809833854 ] }, 
    "start time" : ISODate("2016-01-01T13:06:52Z"), 
    "stop time" : ISODate("2016-01-01T13:13:42Z"), 
    "dist" : { "location" : 109757.75937287517 }  #显示指定坐标与文档中坐标之间的距离
}

# 查询
db.trips.aggregate([
    {
    $geoNear:{
        near:[-73,40], # 使用2d索引
        distanceField : "dist.location", 
        key : "end station location.coordinates" }  
    }       
])

Hash索引

Hash索引是指使用某字段进行Hash计算之后的值来建立索引。主要使用在分片的片键上。 hash索引的特点

  • MongoDB只支持单字段的Hash索引,不能创建多字段的Hash索引
  • 不同的值在Hash后可能相同,所以Hash索引不能设定为唯一约束
  • 创建Hash索引的字段可可以同时创建其他索引
  • hash索引支持相等查询,但不支持范围查询

示例:将Product集合中的ProductName字段设为Hash索引 db.Product.createIndex({"ProductName":"hashed"})

重建索引

当索引出现损坏时,可以尝试用reIndex方法重建索引。该方法实际上是将集合中的索引全部删除后再依序重新创建。 对于副本集来说,重建索引只会在当前的mongod实例中进行,并不会同步至其他节点。 db.collection.reIndex() 示例:将Product集合中的索引全部重建 db.Product.reIndex() 重建索引需要具有dbAdmin角色

查询索引

查询集合中的所有索引信息

db.collection.getIndexes()

# 查询Product集合中的索引信息
db.Product.getIndexes()
[
        {
                "v" : 2,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_"
        },
        {
                "v" : 2,
                "key" : {
                        "ProductName" : "hashed"
                },
                "name" : "ProductName_hashed"
        }
]

查询所有索引的大小

db.collection.totalIndexSize() 查询结果的单位是byte

db.zips.totalIndexSize()
495616

删除索引

删除指定的索引

db.collection.dropIndex()

删除_id外的所有索引

db.collection.dropIndexes()

# 删除Product集合中名称为Weight的索引
db.Product.dropIndex("Weight")
# 删除Product集合中除了_id字段的其他索引
db.Product.dropIndexes()