地理空间索引与查询,索引类型和属性

必赢365net手机版 19

 一、经纬度表示方式

    MongoDB
中对经纬度的存储有着自己的一套规范(主要是为了可以在该字段上建立地理空间索引)。包括两种方式,分别是 Legacy
Coordinate Pairs
(这个词实在不知道怎么翻译…) 和  GeoJSON 。

  • Legacy Coordinate Pairs

Legacy Coordinate Pairs
又有两种方式可以存储经纬度,可以使用数组(首选)或嵌入式文档。

数组:

<field>: [<longitude>,
<latitude> ]

嵌入式文档:

<field>: { <field1>: <longitude>, <field2>: <latitude> }

tips:有效经度值介于-180和180之间。有效纬度值介于-90和90之间。

  • GeoJSON

GeoJson
比 Legacy Coordinate Pairs 要强大的多,Legacy Coordinate Pairs
仅仅用来保存一个经纬度,而 GeoJson
可以用来指定点、线和多边形。

点可以用形如[longitude,
latitude]([经度,纬度])的两个元素的数组表示:

{
“geometry”: {
        “type”: “Point”,
        “coordinates”: [125.6,
10.1]
   }
}

线可以用一个由点组成的数组来表示:

{
“geometry”: {
        “type”: “LineString”,
         “coordinates”: [[125.6,
10.1],[125.6,10.2],[125.6,10.3]]
   }
}

多边形的表示方式与线一样(都是一个由点组成的数组),但是”type”不同:

{
“geometry”: {
        “type”: “Polygon”,
         “coordinates”: [[125.6,
10.1],[125.5,10.2],[125.7,10.3]]
  }
}

type 除了
Point(点)、LineString(线)、Polygon(多边形),还有 MultiPoint(多点)、MultiLineString(多个线)
和  MultiPolygon(多个多边形)。

“geometry”字段的名字可以是任意的,但是其中的子对象是由GeoJSON指定的,不能改变。

索引类型

MongDB的索引分为以下几种类型:单键索引、复合索引、多键索引、地理空间索引、全文本索引和哈希索引

二、地理空间索引

  • 2dsphere索引

2dsphere索引用于地球表面类型的地图,允许使用在 Legacy Coordinate Pairs
保存的经纬度字段上和使用GeoJSON格式保存的点、线和多边形字段上。

  db.world.ensureIndex({"geometry" : "2dsphere"})
  • 2d索引

必赢365net手机版, 对于非球面地图(游戏地图、时间连续的数据等),可以使用”2d”索引代替”2dsphere”。

 2d 索引 仅允许使用在 Legacy Coordinate Pairs 保存的经纬度字段上。

  db.world.ensureIndex({"geometry" : "2d"})
  • 区别:

2dsphere索引只支持球形查询(即球面上几何图形的查询)。

2d索引支持平面查询(即在平面上几何图形的查询)和一些球形查询。虽然2d索引支持一些球形查询,但是对这些球形查询使用2d索引可能会导致错误,例如极点附近会出现大量的扭曲变形。
2d索引只能对点进行索引。可以保存一个由点组成的数组,但是它只会被保存为由点组成的数组,不会被当成线。特别是对于”$geoWithin”查询来说,这是一项重要的区别。如果将街道保存为由点组成的数组,那么如果其中的某个点位于给定的形状之内,这个文档就会与$geoWithin相匹配。但是,由这些点组成的线并不一定完全包含在这个形状之内。

单键索引(Single Field Indexes)

在一个键上创建的索引就是单键索引,单键索引是最常见的索引,如MongoDB默认创建的_id的索引就是单键索引。

例子:

{
    "_id" : ObjectId(...),
    "name" : "Alice",
    "score" : 27
}

如果要在如上的文档中创建单键索引,语句如下:

db.users.ensureIndex( { "score" : 1 } )

其存储结构如下图:

必赢365net手机版 1

如果想要在子文档的一个键上建立单键索引,其例子如下:

{
    "_id": ObjectId(...),
    "name": "John Doe",
    "address": {
        "street": "Main",
        "zipcode": "53511",
        "state": "WI"
    }
}

结构如上,其创建语句如下:

db.users.ensureIndex( { "address.zipcode": 1 } )

如果想要在整个子文档上建立单键索引,其例子如下:

{
    _id: ObjectId(...),
    metro: {
        city: "New York",
        state: "NY"
    },
    name: "Giant Factory"
}

结构如上,其创建语句如下:

db.factories.ensureIndex( { metro: 1 } )

下面的语句能够使用其索引查找到上面的数据:

db.factories.find( { metro: { city: "New York", state: "NY" } } )

但再下面的这一条语句就查不到数据了,说明子文档的查找必须是精确匹配,包括子文档中的顺序:

db.factories.find( { metro: { state: "NY", city: "New York" } } )

三、地理空间查询

   
可以使用多种不同类型的地理空间查询:交集(intersection)、包含(within)以及接近(nearness)。

  • $geoIntersects

定义:指出与查询位置相交的文档。

支持的索引:2dsphere

几何操作符:

    1. $geometry (仅支持 2dsphere 索引,指定GeoJSON格式的几何图形)
  • $geoWithin

定义:指出完全包含在某个区域的文档。

支持的索引:2dsphere、2d

几何操作符:

  1. $box(仅支持 2d 索引,查询出矩形范围内的所有文档)
  2. $center(仅支持 2d 索引,查询出圆形范围内的所有文档)
  3. $polygon (仅支持 2d 索引,查询出多边形范围内的所有文档)
  4. $centerSphere(支持 2d 索引和 2dsphere
    索引,查询出球面圆形范围内的所有文档)
  5. $geometry (仅支持 2dsphere 索引,指定GeoJSON格式的几何图形)
  • $near

定义:指出与查询位置从最近到最远的文档。

支持的索引:2dsphere、2d

几何操作符:

  1. $maxDistance (支持 2dsphere 索引和 2d
    索引,指定查询结果的最大距离)
  2. $minDistance (仅支持 2dsphere
    索引,指定查询结果的最小距离。在4.0后支持 2d 索引)
  3. $geometry (仅支持 2dsphere 索引,指定GeoJSON格式的点)

备注:$minDistance 官方文档说仅支持
2dsphere 索引,但是我实践证明 $minDistance 也支持 2d
索引,大家可以试试看,这里保留争议。

  • $nearSphere

定义:使用球面几何计算近球面的距离,指出与查询位置从最近到最远的文档。

支持的索引:2dsphere、2d

几何操作符:

  1. $maxDistance (支持 2dsphere 索引和 2d
    索引,指定查询结果的最大距离)
  2. $minDistance (仅支持 2dsphere
    索引,指定查询结果的最小距离。在4.0后支持 2d 索引)
  3. $geometry (仅支持 2dsphere 索引,指定GeoJSON格式的点)

备注:MongoDB 4.0 后对地理空间索引增加的支持?

1、地理空间查询操作符 $near 和 $nearSphere
支持查询的分片集合。

2、MongoDB
4.0 为 $geoNear 聚合运算符和 geoNear 命令添加了一个选项
key,使用户可以在查询时指定要使用的地理空间索引。以前,要使用 $geoNear
聚合运算符或 geoNear 命令,集合只能有一个地理空间索引。

 

db.places.aggregate([
   {
     $geoNear: {
        near: { type: "Point", coordinates: [ -73.98142 , 40.71782 ] },
        key: "location",
        distanceField: "dist.calculated",
        query: { "category": "Parks" }
     }
   }
])

 

复合索引(Compound Indexes)

在多个键上建立的索引就是复合索引。

例子:

{
    "_id": ObjectId(...),
    "userid": "aa1",
    "category": ["food", "produce", "grocery"],
    "location": "4th Street Store",
    "score": 4
}

如果要在如上的文档中创建复合索引,语句如下:

db.products.ensureIndex( { "userid": -1, "score": 1 } )

userid是正序排列,score是逆序排列的。其存储结构如下图:

必赢365net手机版 2

这个索引可以支持如下的排序:

db.products.find().sort( { userid: 1, score: -1 } );
db.products.find().sort( { userid: -1, score: 1 } );
db.products.find().sort( { userid: 1 } );
db.products.find().sort( { userid: -1 } );

不能支持如下的排序:

db.products.find().sort( { userid: 1, score: 1 } );
db.products.find().sort( { userid: -1, score: -1 } );
db.products.find().sort( { score: 1 } );
db.products.find().sort( { score: -1 } );

四、实践

  • “$geoIntersects” 操作符找出与查询位置相交的文档 ?

必赢365net手机版 3必赢365net手机版 4

db.driverPoint.find(
   {
     coordinate: {
       $geoIntersects: {
          $geometry: {
             type: "Polygon" ,
             coordinates: [
               [ [ 118.193828, 24.492242 ], [ 118.193953, 24.702114 ], [ 118.19387, 24.592242 ],[ 118.193828, 24.492242 ]]
             ]
          }
       }
     }
   }
)

View Code

 tips:coordinates 表示多边形,第一个点 和
最后一个点 必须相同,因为这样才能拼成一个多边形呀!

  • “$geoWithin”操作符找出完全包含在某个区域的文档?

必赢365net手机版 5必赢365net手机版 6

db.driverPoint.find(
   {
     coordinate: {
       $geoWithin: {
          $geometry: {
             type: "Polygon" ,
             coordinates: [
               [ [ 118.193828, 24.492242 ], [ 118.193953, 24.702114 ], [ 119.19387, 28.792242 ],[ 118.193828, 24.492242 ]]
             ]
          }
       }
     }
   }
)

View Code

  • “$geoWithin”操作符找出矩形范围内的文档?

必赢365net手机版 7必赢365net手机版 8

db.driverPoint.find(
{
  coordinate: {
     $geoWithin: {
        $box: [
          [ 118.0,24.0 ],
          [ 120.0,30.0 ]
        ]
     }
  }
}
)

View Code

 tips:”$box”接受一个两元素的数组:第一个元素指定左下角的坐标,第二个元素指定右上角的坐标。

  • “$geoWithin”操作符找出圆形范围内的文档?

必赢365net手机版 9必赢365net手机版 10

db.driverPoint.find(
{
  coordinate: {
     $geoWithin: {
         $center: [ [ 118.067678, 24.444373] , 10 ] 
     }
  }
}
)

View Code

tips:”$center”接受一个两元素数组作为参数:第一个元素是一个点,用于指定圆心;第二个参数用于指定半径。

  • “$geoWithin”操作符找出多边形范围内的文档?

必赢365net手机版 11必赢365net手机版 12

db.driverPoint.find(
{
  coordinate: {
     $geoWithin: {
         $polygon: [ [ 118.067678 , 24.444373 ], [ 119.067678 , 25.444373 ], [ 120.067678 , 26.444373 ] ]
     }
  }
}
)

View Code

tips:”$polygon”
列表中的最后一个点会被连接到第一个点,以便组成多边形。

  • “$geoWithin”操作符找出球面圆形范围内的文档?

必赢365net手机版 13必赢365net手机版 14

db.driverPoint.find(
{
  coordinate: {
     $geoWithin: {
         $centerSphere: [ [ 118.067678, 24.444373 ], 10/3963.2 ]
     }
  }
}
)

View Code

tips:该例子表示 距离 [118.067678,
24.444373] 中心点10
英里范围内的所有文档,查询通过除以地球的大约赤道半径(3963.2英里)将距离转换为弧度。

  • $near 找出距离一个点相应距离内的文档?

geoJson 格式(仅支持 2dsphere 索引):

必赢365net手机版 15必赢365net手机版 16

db.driverPoint.find(
{
   coordinate: {
     $near: {
       $geometry: {
          type: "Point" ,
          coordinates: [ 118.067678 , 24.444373 ]
       },
       $maxDistance: 3000,
       $minDistance: 0
     }
   }
}
)

View Code

Legacy Coordinate Pairs 格式(仅支持 2d 索引):

必赢365net手机版 17必赢365net手机版 18

db.driverPoint.find(
{
   coordinate: {
     $near: [ 118.193828 , 24.492242 ],
     $maxDistance: 0.10
     }
}
)

View Code

tips:1、$near 当用 geoJson
格式表示时, 距离单位是米(meter)。

         2、$near 当用 Legacy Coordinate Pairs
格式表示时,距离单位是弧度(radian)。  

       
 3、”$near”是唯一一个会对查询结果进行自动排序的地理空间操作符:”$near”的返回结果是按照距离由近及远排序的。

多键索引(Multikey Index)

如果在一个数组上面创建索引,MongoDB会自己决定,是否要把这个索引建成多键索引。

如果数据结构如下(两种):

{a: [1, 2], b: 1}
{a: 1, b: [1, 2]}

你可以创建{ a: 1, b: 1 },会是多键复合索引。

多键索引结构如下:

必赢365net手机版 19

 

例子:

{
    "_id" : ObjectId("..."),
    "name" : "Warm Weather",
    "author" : "Steve",
    "tags" : [ "weather", "hot", "record", "april" ]
}

文档结构如上,如果你在tags上创建索引,就会创建出多键索引

如果文档结构如下:

{
    "_id": ObjectId(...),
    "title": "Grocery Quality",
    "comments": [{
        author_id: ObjectId(...),
        date: Date(...),
        text: "Please expand the cheddar selection."
    }, {
        author_id: ObjectId(...),
        date: Date(...),
        text: "Please expand the mustard selection."
    }, {
        author_id: ObjectId(...),
        date: Date(...),
        text: "Please expand the olive selection."
    }]
}

创建{ “comments.text”: 1 }
索引也会是多键索引,且在如下查找语句中有效:

db.feedback.find( { "comments.text": "Please expand the olive selection." } )

五、结语

   
怎么说呢?学习这方面的知识老是给我一种特别乱的感觉。稍微总结下吧!MongoDB
对于地理空间的查询 是基于 它对 地理空间的索引(即2dsphere 和
2d)来实现的。所以,我们只要搞清楚什么时候 该建立 2dsphere
索引,什么时候该建立 2d
索引,然后再找适用于该索引的操作符就很清晰明了了!总之,geoJSON
格式保存的经纬度一定 建立 2dsphere 索引。Legacy Coordinate Pairs
格式保存的经纬度 仅在表示 平面地图的时候才考虑建立 2d
索引,其他情况还是选择 2dsphere 索引。

    Spring Data MongoDB 中对地理位置的查询可参考 https://github.com/JMCuixy/SpringDataMongoDB 中单元测试的
Test03.java。

 

 

参考资料:

1、《MongoDB 权威指南第二版》

2、

地理空间索引(Geospatial Indexes and Queries)

MongoDB支持几种类型的地理空间索引。其中最常用的是 2dsphere
索引(用于地球表面类型的地图)和 2d
索引(用于平面地图和时间连续的数据)。

1) 2dsphere

2dsphere
允许使用GeoJSON格式(http://www.geojson.org)指定点、线和多边形。

点可以用形如[longitude, latitude]([经度,
纬度])的两个元素的数组表示:

{
    "name" : "New York City",
    "loc" : {
        "type" : "Point",
        "coordinates" : [50, 2]
    }
}

线可以用一个由点组成的数组来表示:

{
    "name" : "Hudson River",
    "loc" : {
        "type" : "LineString",
        "coordinates" : [[0, 1], [0, 2], [1, 2]]
    }
}

多边形是由线组成的数组来表示:

{
    "name" : "New England",
    "loc" : {
        "type" : "Polygon",
        "coordinates" : [[[0, 1], [0, 2], [1, 2], [0, 1]]]
    }
}

2dsphere
支持 Point、MultiPoint、LineString、MultiLineString、Polygon、MultiPolygon、Geometry
Collection

loc 字段的名字可以是任意的,但是其中子对象是由 GeoJSON
指定的,不能改变。

在 ensureIndex 中使用 2dsphere 选项就可以创建一个地理空间索引:

db.world.ensureIndex({"loc": "2dsphere"})

可以使用多种不同的地理空间查询:交集(intersection)、包含(within)以及接近(nearness)。查询时,需要将希望查找的内容指定为形如
{“$geometry”:geoJsonDesc} 的 GeoJSON 对象。

交集(intersection),使用 $geoIntersects 操作符:

var place = {
    "type" : "Polygon",
    "coordinates" : [[[0, 1], [0, 3], [50, 2], [0, 1]]]
}
db.world.find({"loc" : {"$geoIntersects" : {"$geometry" : place}}})

会查找出所有与 place 有交集的文档。

包含(within),使用 $within 或者 $geoWithin 操作符:

db.world.find({"loc" : {"$within" : {"$geometry" : place}}})

接近(nearness),使用 $near 或者 $geoNear 操作符:

var place = {
    "type" : "Point",
    "coordinates" : [0, 3]
}
db.world.find({"loc" : {"$near" : {"$geometry" : place}}})

place 必须是个点,$near
是唯一一个会对查询结果进行自动排序的地理空间操作符,$near
的返回结果是按照距离由近及远排序的。

2) 2d

2d
索引用于扁平化表面,而不是球体表面,否则极点附近会出现大量的扭曲变形。

文档中使用包含两个元素的数组表示 2d 索引字段,不是 GeoJSON 的格式。

{
    "name": "Water Temple",
    "tile": [32, 22]
}

2d
索引只能对点进行索引。可以保存一个由点组成的数组,但是它只会被保存为由点组成的数组,不会被当成线。特别是对
$within 查询来说,数组中的某个点在查询范围内,该文档就会被找出。

在 ensureIndex 中使用 2d
选项就可以创建一个地理空间索引,也可以在其中设置最大最小边界值和精度。默认情况下,最大值和最小值的范围是[
-180 , 180 ),精度是26位的精度,大致相当于2英尺或60厘米的精度:

db.places.ensureIndex({"tile" : "2d"}, {"min" : -90, "max" : 90, "bits" : 20})

这会创建一个180*180大小的空间索引。

2d 索引的查询比 2dsphere 简单许多,可以直接使用$near 和
$within,而不必带有 $geometry 子对象:

db.places.find({"tile": {"$near": [20, 21]}}).limit(10)

如果不加 limit,默认最多返回100条。

$within
可以查询出某个形状里的所有文档,可以是矩形($box)、圆形($center)或者多边形($polygon)。

db.places.find({"tile": {"$within": {"$box": [[0, 0], [30, 30]]}}})

$box
接收两个元素,第一个元素是矩形的左下角坐标,第二个元素是矩形的右上角坐标。

db.places.find({"tile": {"$within": {"$center": [[30, 30], 10]}}})

$center 也接收两个元素,第一个元素是圆心点的坐标,第二个是圆的半径。

db.places.find({"tile": {"$within": {"$polygon": [[0, 0], [30, 30], [0, 25]]}}})

$polygon 接收多个点组成的数组,用来指定多边形。

不管是 2dsphere 索引还是 2d 索引,都可以和其他字段一起组成复合索引:

db.world.ensureIndex({"name": 1, "loc": "2dsphere"})

全文索引(Text Indexes)

全文索引用于在文档中搜索文本,我们也可以使用正则表达式来查询字符串,但是当文本块比较大的时候,正则表达式搜索会非常慢,而且无法处理语言理解的问题(如
entry 和 entries
应该算是匹配的)。使用全文索引可以非常快地进行文本搜索,就如同内置了多种语言分词机制的支持一样。创建索引的开销都比较大,全文索引的开销更大。创建索引时,需后台或离线创建。

{
    "_id" : ObjectId("55a0e30427c9370e525032e9"),
    "content" : "This morning I had a cup of coffee.",
    "about" : "beverage",
    "keywords" : [
        "coffee"
    ]
}
{
    "_id" : ObjectId("55a0e31027c9370e525032ea"),
    "content" : "Who doesn't like cake?",
    "about" : "food",
    "keywords" : [
        "cake",
        "food",
        "dessert"
    ]
}

文档如上所示,在 content 上创建全文索引:

db.article.ensureIndex({"content": "text"})

使用全文索引查询内容:

db.article.find({"$text": {"$search": "coffee"}})

如果要在所有字符串的键上进行文本搜索,请使用通配符 ($**)
来索引所有的包含字符串的键。创建了一个
article 中所有文档的所有键的字符串进行索引的索引,且命名为 TextIndex:

db.article.ensureIndex({"$**": "text"}, {"name": "TextIndex"})

被索引的数据的默认语言决定了如何解析词根以及忽略停止词的规则。被索引数据的默认语言是英语。如果希望指定一个不同的语言,在创建全文索引时使用 default_language 选项。

支持如下语言(不支持中文,至少在 2.6 的版本中是这样的):

  • da or danish
  • nl or dutch
  • en or english
  • fi or finnish
  • fr or french
  • de or german
  • hu or hungarian
  • it or italian
  • nb or norwegian
  • pt or portuguese
  • ro or romanian
  • ru or russian
  • es or spanish
  • sv or swedish
  • tr or turkish

注:如果您将语言指定为值 "none" ,那么 text search
会使用简单的分词器,没有停止词也没有取词根处理。

db.quotes.ensureIndex({"content": "text"}, {"default_language": "spanish"})

哈希索引(Hashed Index)

哈希索引可以支持相等查询,但是哈希索引不支持范围查询。您可能无法创建一个带有哈希索引键的复合索引或者对哈希索引施加唯一性的限制。但是,您可以在同一个键上同时创建一个哈希索引和一个递增/递减(例如,非哈希)的索引,这样MongoDB对于范围查询就会自动使用非哈希的索引。

db.active.ensureIndex({"a": "hashed"})

 上面的操作将会在 active 的 a 键上创建一个哈希索引。

索引属性

MongDB的索引属性有以下几种:TTL索引、唯一索引和稀疏索引。

TTL索引(TTL Indexes)

TTL索引是一种特殊索引,通过这种索引MongoDB会过一段时间后自动移除集合中的文档。这对于某些类型的信息来说是一个很理想的特性,例如机器生成的事件数据、日志、会话信息等,这些数据都只需要在数据库中保存有限时间。

TTL索引有如下限制:

  • 它不支持复合索引 。

  • 被索引键必须是日期类型的数据。

  • 如果这个键存储的是一个数组,且在索引中有多个日期类型的数据(和一篇文档关联),那么当其中最低 (比如,最早)过期阀值得到匹配时,这篇文档就会过期失效了。

TTL索引不能保证过期数据会被立刻删除。在文档过期和MongoDB从数据库中删除文档之间,可能会有延迟。删除过期数据的后台任务 每隔60秒 运行一次。所以,在文档过期 之后 和
后台任务运行或者结束 之前 ,文档会依然存在于集合中。删除操作的持续实际取决于您的 mongod 实例的负载。因此,在两次后台任务运行的间隔间,过期数据可能会继续留在数据库中超过60秒。在其他方面,TTL索引是普通索引,并且如果可以的话,MongoDB会使用这些索引来匹配任意查询。

db.token.ensureIndex({"lastUpdated": 1}, {"expireAfterSecs": 60*60*24})

token 超过24小时就会被删除掉。

唯一索引(Unique Indexes)

唯一索引可以拒绝保存那些被索引键的值已经重复的文档。

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

默认情况下,MongoDB索引的 unique 属性是 false 。如果对复合索引施加唯一性的限制,那么MongoDB就会强制要求复合值的唯一性,而不是分别对每个单独的值要求唯一。

唯一性的限制是针对一个集合中不同文档的。也即,唯一索引可以防止 不同
文档的被索引键上存储相同值,但是它不禁止同一篇文档在被索引键存储的数组里存储的元素或者内嵌文档是相同的值。在同一篇文档存储重复数据的情况下,重复的值只会被存入索引一次。

例如,一个集合有一个唯一索引 a.b :

db.collection.ensureIndex({"a.b": 1 }, {unique: true})

假如在集合中没有其他的文档的 a.b 键的值是 5 ,那么唯一索引将会允许将以下文档插入集合:

db.collection.insert({a: [{b: 5}, {b: 5}]})

如果一篇文档不包含唯一索引的被索引键,那么索引默认会为该文档存储一个null值。由于唯一性的限制,MongoDB将只允许有一篇可以不包含被索引键。如果超过一篇文档不包含被索引键或没有值,那么会抛出键重复(duplicate
key)错误导致索引创建失败。可以组合使用唯一性和稀疏索引的特性来过滤那些包含null值的文档以避免这个错误。

稀疏索引(Sparse Indexes)

稀疏索引会跳过所有不包含被索引键的文档。这个索引之所以称为 “稀疏”
是因为它并不包括集合中的所有文档。与之相反,非稀疏的索引会索引每一篇文档,如果一篇文档不含被索引键则为它存储一个null值。

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

如果一个索引会导致查询或者排序的结果集是不完整的,那么MongoDB将不会使用这个索引,除非用户使用
hint() 方法来显示指定索引。例如,查询 { x: { $exists: false } }
将不会使用 x 键上的稀疏索引,除非显示的hint。

2dsphere (version 2), 2d 和 text 这些索引总是稀疏的。

只要一篇文档里有至少一个被索引键,稀疏且只包含有递增/递减索引键的复合索引就会索引这篇文档。

至于稀疏且包含有地理索引键(例如 2dsphere,
2d)以及递增/递减索引键的复合索引,只有地理索引键的存在与否能决定一篇文档是否被索引。

至于稀疏且包含了全文索引键和其他递增/递减索引键的复合索引,只有全文索引键的存在与否能决定是否索引该文档。

一个稀疏且唯一的索引,可以防止集合中的文档被索引键中出现重复值,同时也允许多个文档里不包含被索引键。

 

参考:MongoDB 2.6
中文文档

Leave a Comment.