Bootstrap

MongoDB 索引

目录

介绍

创建索引

删除索引

删除单个索引

删除多个索引

删除 _id 索引之外的所有索引

索引的类型

单字段索引

复合索引

多键索引

边界

通配符

地理空间索引

2dsphere

什么是 GeoJSON?

点(Point)

线(LineString)

多边形(Polygon)

 多点(MultiPoint)

线组(MultiLineString)

 多多边形(MultiPolygon)

几何集合(GeometryCollection)

创建 2dsphere

查询 2dsphere 

Polygons

球 

交叉点

球体中的圆

2d

2d 的创建

精度 

位置范围

查询 2d

曲面上的点

曲面上的形状

文本索引

 注意事项

应用场景

哈希索引

聚集索引

使用场景

注意事项


介绍

我们先简单了解一下索引:索引的本质就是一个排序的列表,在这个列表中存储着索引的值和包含这个值的数据 (数据row或者document) 的物理地址,索引可以大大加快查询的速度,这是因为使用索引后可以不再扫描全表来定位某行的数据,而是先通过索引表找到该行数据对应的物理地址(多数为B-tree查找),然后通过地址来访问相应的数据。

创建索引

示例

db.blog.createIndex(
   {
     content: "text",
     "users.comments": "text",
     "users.profiles": "text"
   },
   {
     name: "InteractionsTextIndex"
   }
)

查看创建的索引

db.blog.getIndexes()

输出的结果

[
  { v: 2, key: { _id: 1 }, name: '_id_' },
  {
    v: 2,
    key: { _fts: 'text', _ftsx: 1 },
    name: 'InteractionsTextIndex',
    weights: { content: 1, 'users.comments': 1, 'users.profiles': 1 },
    default_language: 'english',
    language_override: 'language',
    textIndexVersion: 3
  }
]

注意

  • 索引名称必须是唯一的。使用已有索引的名称创建索引会报错。

  • 如果您在创建索引时未指定名称,系统会用下划线将每个索引键字段和值连接起来,从而生成新索引的名称。

删除索引

db.collection.dropIndex()     从集合中删除特定索引。

db.collection.dropIndexes()      从集合或索引数组中删除所有可移动索引(如果指定)。

删除单个索引

db.<collection>.dropIndex("<indexName>")

删除多个索引

db.<collection>.dropIndexes( [ "<index1>", "<index2>", "<index3>" ] )

注意:方法名多了个 es

删除 _id 索引之外的所有索引

db.<collection>.dropIndexes()

索引的类型

单字段索引

单个字段索引收集集合内每个文档中单个字段的数据,并对其排序。

值 1 表示升序,-1 表示降序

例如:这个地方就是给 gpa 添加了一个升序索引

db.students.createIndex( { gpa: 1 } )

对嵌入字段创建索引 

什么是嵌入式文档呢?

恰似 JSON 的嵌套字段即对象1里面还有对象2甚至更多,那么对象2就是对象1的嵌套

例如:state 就是 location 的嵌套文档(对象2),这个地方就是给 state 创建一个升序索引

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

复合索引

复合索引从集合中每个文档的两个或多个字段收集数据并对其排序。数据先按索引中的第一个字段分组,再按每个后续字段分组。

类似 MYSQL 的一表多主键的机制,知道 MYSQL 的复合主键,那么理解 MongoDB 的复合主键应该会很快

例如:把 name 设置成升序,gpa 设置成降序,两个合在一起就是一个索引,这个索引就是复合索引

db.students.createIndex( {
   name: 1,
   gpa: -1
} )

那么,复合索引有什么作用呢?

复合索引可以加速涉及多个字段的查询,包括等值查询、范围查询和排序操作。

相较于单字段索引,复合索引对性能有更重要的影响

多键索引

多键索引收集数组中存储的数据并进行排序。

您无需显式指定多键类型。对包含数组值的字段创建索引时,MongoDB 会自动将该索引设为多键索引。

主要还是作用在 数组 上的一个索引

模拟一些数据

db.students.insertMany( [
   {
      "name": "Andre Robinson",
      "test_scores": [ 88, 97 ]
   },
   {
      "name": "Wei Zhang",
      "test_scores": [ 62, 73 ]
   },
   {
      "name": "Jacob Meyer",
      "test_scores": [ 92, 89 ]
   }
] )

 这就是给 test_scores 添加一个升序索引

db.students.createIndex( { test_scores: 1 } )

对于内嵌数组类型的索引,和上诉的内嵌是差不多的,这里就不过多赘述了 

边界

索引边界定义了 MongoDB 使用索引执行查询时搜索的索引值的范围。 当您在索引字段上指定多个查询谓词时,MongoDB 会尝试合并这些谓词的边界,以生成边界更小的索引扫描。 较小的索引边界可加快查询速度并减少资源使用。

说白了就是在查询时增加了一些限制条件,比如大于小于等,给查询规定在一个范围内实现更快的查找数据

例如

db.students.find( { grades: { $gte: 90, $lte: 99 } } )

更多的信息还是查看官网:多键索引边界 - MongoDB 手册 v 7 。 0

通配符

使用 ($**) 即为通配符

什么是通配符?

使用通配符索引来支持对事先不知道或因文档而异的字段名称的查询

实现模糊查找时就可以使用 通配符

例如

db.products.insertMany( [
   {
      "product_name" : "Spy Coat",
      "attributes" : {
         "material" : [ "Tweed", "Wool", "Leather" ],
         "size" : {
            "length" : 72,
            "units" : "inches"
         }
      }
   },
   {
      "product_name" : "Spy Pen",
      "attributes" : {
         "colors" : [ "Blue", "Black" ],
         "secret_feature" : {
            "name" : "laser",
            "power" : "1000",
            "units" : "watts",
         }
      }
   }
] )

创建一个通配符索引

db.products.createIndex( { "attributes.$**" : 1 } )

 查询

db.products.find( { "attributes.material" : "Leather" } )
[
  {
    _id: ObjectId("63472196b1fac2ee2e957ef6"),
    product_name: 'Spy Coat',
    attributes: {
      material: [ 'Tweed', 'Wool', 'Leather' ],
      size: { length: 72, units: 'inches' }
    }
  }
]

地理空间索引

地理空间索引可提高对地理空间坐标数据进行查询的性能。要了解详情,请参阅地理空间索引。

MongoDB 提供两种类型的地理空间索引:

  • 使用平面几何返回结果的 2d 索引。
  • 使用球面几何返回结果的 2dsphere 索引。

2dsphere

2dsphere 索引支持对类似地球的球体进行地理空间查询。

  • 确定指定区域内的点。

  • 计算到指定点的距离。

  • 返回坐标查询的精确匹配结果。

被索引字段的值必须为以下二者之一:

  • GeoJSON 对象
  • 传统坐标对

对于传统坐标对,2dsphere 索引将数据转换为 Geo JSON 点。

什么是 GeoJSON?

GeoJSON 是一种基于 JSON (JavaScript Object Notation) 的格式,用于表示各种地理数据结构。它是基于 JSON 的一种标准,用于编码地理信息,包括点、线、面(多边形)以及其他地理集合。GeoJSON 通常用于 Web 地图和地理信息服务中,以便于数据的传输和处理。

点(Point)

表示一个地理位置上的单个点。

{ "type": "Point", "coordinates": [125.6, 10.1] }
线(LineString)

表示一系列由线段连接的点。 

{ "type": "LineString", "coordinates": [ [125.6, 10.1], [125.6, 10.2] ] }
多边形(Polygon)

表示一个由线(闭合线)包围的区域,多边形的最后一个点必须与第一个点相同,形成一个闭合的环路。

{ "type": "Polygon", "coordinates": [ [ [125.6, 10.1], [125.6, 10.2], [125.7, 10.2], [125.7, 10.1], [125.6, 10.1] ] ] }
 多点(MultiPoint)

表示多个点的集合。

{ "type": "MultiPoint", "coordinates": [ [100.0, 0.0], [101.0, 1.0] ] }
线组(MultiLineString)

表示多条线段的集合。

{ "type": "MultiLineString", "coordinates": [ [ [100.0, 0.0], [101.0, 1.0] ], [ [102.0, 2.0], [103.0, 3.0] ] ] }
 多多边形(MultiPolygon)

表示多个多边形的集合。

{ "type": "MultiPolygon", "coordinates": [ 
  [ [ [102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0], [102.0, 2.0] ] ],
  [ [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ] ]
] }
几何集合(GeometryCollection)

表示多个几何对象的集合。 

{
  "type": "GeometryCollection",
  "geometries": [
    { "type": "Point", "coordinates": [100.0, 0.0] },
    { "type": "LineString", "coordinates": [ [100.0, 0.0], [101.0, 1.0] ] }
  ]
}

GeoJSON 对象通常包含一个 type 字段,用于指定它所表示的几何类型,以及一个 coordinates 字段,包含了具体的坐标数据。这些坐标通常是经纬度对,表示在地球表面上的位置。

GeoJSON 也支持包含属性(properties),这是一组键值对,用于存储与几何相关的信息,例如:

{
  "type": "Feature",
  "geometry": {
    "type": "Point",
    "coordinates": [125.6, 10.1]
  },
  "properties": {
    "name": "Dinagat Islands",
    "population": 1800
  }
}
创建 2dsphere

创建一个 places 集合 

db.places.insertMany( [
   {
      loc: { type: "Point", coordinates: [ -73.97, 40.77 ] },
      name: "Central Park",
      category : "Park"
   },
   {
      loc: { type: "Point", coordinates: [ -73.88, 40.78 ] },
      name: "La Guardia Airport",
      category: "Airport"
   },
   {
      loc: { type: "Point", coordinates: [ -1.83, 51.18 ] },
      name: "Stonehenge",
      category : "Monument"
   }
] )

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

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

查询多边形内的位置

使用$geoWithin来查询collection。以下$geoWithin查询指定一个具有四个顶点的多边形(一个矩形)并返回该多边形内的点:

db.places.find( {
   loc: {
      $geoWithin: {
         $geometry: {
            type: "Polygon",
            coordinates: [ [
               [ -73.95, 40.80 ],
               [ -73.94, 40.79 ],
               [ -73.97, 40.76 ],
               [ -73.98, 40.76 ],
               [ -73.95, 40.80 ]
            ] ]
          }
      }
   }
} )

输出

[
  {
    _id: ObjectId("63a4a8d67348ebdcd0a061f0"),
    loc: { type: 'Point', coordinates: [ -73.97, 40.77 ] },
    name: 'Central Park',
    category: 'Park'
  }
]
球 

查询球面上某个点附近的位置

使用$near查询集合。以下$near查询将返回在位于[ -73.92, 40.78 ]的 GeoJSON 点的5000米范围内具有loc字段的文档:

db.places.find( {
   loc: {
      $near: {
         $geometry: {
            type: "Point",
            coordinates: [ -73.92, 40.78 ]
         },
         $maxDistance : 5000
      }
   }
} )

输出

[
  {
    _id: ObjectId("63f7c3b15e5eefbdfef81cab"),
    loc: { type: 'Point', coordinates: [ -73.88, 40.78 ] },
    name: 'La Guardia Airport',
    category: 'Airport'
  },
  {
    _id: ObjectId("63f7c3b15e5eefbdfef81caa"),
    loc: { type: 'Point', coordinates: [ -73.97, 40.77 ] },
    name: 'Central Park',
    category: 'Park'
  }
]
交叉点

查询与 GeoJSON 对象相交的位置

以下$geoIntersects查询指定包含四个点的LineString ,并返回与直线相交的文档:

db.gasStations.find( {
   loc: {
      $geoIntersects: {
         $geometry: {
            type: "LineString",
            coordinates: [
               [ -105.82, 33.87 ],
               [ -106.01, 34.09 ],
               [ -106.31, 35.65 ],
               [ -107.39, 35.98 ]
            ]
          }
      }
   }
} )

输出

[
   {
     _id: ObjectId("63f658d45e5eefbdfef81ca4"),
     loc: { type: 'Point', coordinates: [ -106.31, 35.65 ] },
     state: 'New Mexico',
     country: 'United States',
     name: 'Horizons Gas Station'
   }
]
球体中的圆

查询球面上某个圆圈内的位置

要查询collection,请使用$geoWithin$centerSphere操作符:

db.places.find( {
   loc: {
      $geoWithin: {
         $centerSphere: [
            [ -1.76, 51.16 ],
            10 / 6378.1
         ]
      }
   }
} )

该查询返回loc字段位于经度-1.76 、纬度51.16的点的 10 公里半径内的文档。

输出

[
   {
     _id: ObjectId("63fd205e4a08b5e248c03e32"),
     loc: { type: 'Point', coordinates: [ -1.83, 51.18 ] },
     name: 'Stonehenge',
     category: 'Monument'
   }
]

2d

2D 索引支持对存储为二维平面上的点的数据进行查询。2D 索引用于查询 传统坐标对。

2d 的创建
db.contacts.insertMany( [
   {
      name: "Evander Otylia",
      phone: "202-555-0193",
      address: [ 55.5, 42.3 ]
   },
   {
      name: "Georgine Lestaw",
      phone: "714-555-0107",
      address: [ -74, 44.74 ]
   }
] )

address字段上创建 2d 索引

db.contacts.createIndex( { address : "2d" } )
精度 

address字段上创建 2d 索引。 指定32位的位置精度:

db.contacts.createIndex(
   { address: "2d" },
   { bits: 32 }
)
位置范围

address字段上创建 2d 索引。 Specify the following location bounds:

  • min的 边界-75

  • max的 边界60

db.contacts.createIndex(
   {
      address: "2d"
   },
   {
      min: -75,
      max: 60
   }
)
查询 2d
曲面上的点

使用$near来查询collection。以下$near查询返回具有address字段在坐标对[ -73.92, 40.78 ] 50 米范围内的文档:

db.contacts.find( {
   address: {
      $near: [ -73.92, 40.78 ],
      $maxDistance : 50
   }
} )

输出

[
   {
     _id: ObjectId("640a3dd9c639b6f094b00e89"),
     name: 'Georgine Lestaw',
     phone: '714-555-0107',
     address: [ -74, 44.74 ]
   }
]

结果按与查询点的距离从最近到最远排序。

曲面上的形状

使用$geoWithin查询contactscollection。以下$geoWithin查询使用$box操作符返回出现在指定矩形内的文档:

db.contacts.find( {
   address: {
      $geoWithin: {
         $box: [ [ 49, 40 ], [ 60, 60 ] ]
      }
   }
} )

输出

[
  {
    _id: ObjectId("647e4e496cdaf4dc323ec92a"),
    name: 'Evander Otylia',
    phone: '202-555-0193',
    address: [ 55.5, 42.3 ]
  }
]

文本索引

文本索引支持对包含字符串内容的字段进行文本搜索查询。

db.collection.createIndex({ field1: "text", field2: "text", ... })

创建文本索引后,可以使用 $text 查询操作符来执行文本搜索:

db.collection.find({ $text: { $search: "search string" } })

 注意事项

  1. 性能影响:全文索引的创建和维护可能会增加数据库写入的性能开销。
  2. 分词器:MongoDB 使用分词器将文本字段分解为单词进行索引和搜索。默认情况下,MongoDB 使用英文分词器,但可以根据需要配置不同的分词器来适应不同的语言和需求。
  3. 文本字段限制:全文索引仅适用于文本字段,对于其他字段类型,如数值或日期,需要使用其他类型的索引。

应用场景

文本索引适用于多种场景,如内容管理系统(CMS)、电子商务平台和日志分析系统,用于搜索文章、商品名称、描述和日志数据等。

哈希索引

要对已包含数据的集合启用分片,必须创建支持分片键的索引。要为空集合启用分片,可以在对集合进行分片时指定分片键索引。

哈希索引支持哈希分片。哈希索引对字段值的哈希值进行索引。

db.orders.createIndex( { _id: "hashed" } )

创建索引后,您可以对 orders 集合进行分片:

sh.shardCollection(
   "<database>.orders",
   { _id: "hashed" }
)

 创建复合哈希索引

db.customers.createIndex(
   {
      "name" : 1
      "address" : "hashed",
      "birthday" : -1
   }
)

创建索引后,您可以对 customers 集合进行分片:

sh.shardCollection(
   "<database>.customers",
   {
      "name" : 1
      "address" : "hashed",
      "birthday" : -1
   }
)

聚集索引

MongoDB 的聚集索引(Compound Index)是一种特殊的索引类型,它允许你按照多个字段进行索引。这意味着索引可以包含多个字段,并且可以按照这些字段的组合进行查询优化

db.users.createIndex({ name: 1, age: -1 })

使用场景

  1. 排序:当你需要按照多个字段进行排序时,聚集索引非常有用。
  2. 覆盖查询:如果查询可以完全通过索引来满足,那么聚集索引可以提高查询效率。
  3. 组合查询:当你需要根据多个字段进行查询时,聚集索引可以优化这类查询。

查询

db.users.find({ name: "John" }).sort({ age: -1 })

注意事项

  1. 索引大小:聚集索引可能会占用更多的空间,因为它需要存储多个字段的值。
  2. 更新成本:当索引的字段值发生变化时,聚集索引的更新成本可能会更高。
  3. 查询优化:不是所有的查询都能从聚集索引中受益,需要根据实际的查询模式来决定是否创建聚集索引。

以上就是关于 MongoDB 索引的所有信息了

;