OPTIONS
翻译或纠错本页面

2d 索引原理

这篇文档对MongoDB的 2d 地理索引提供了更深层次的内在机制解释。这份材料对于普通操作或者应用开发并不是必要的,但是对于故障排除或者想要更多了解的用户也许有用。

2d 索引计算Geohash值

当您基于 普通坐标 创建索引,MongoDB会在给定 位置范围 内的为坐标计算 geohash 并索引该geohash值。

为了计算geohash, 需要迭代地把一个二维区域划分为四个象限。然后,给每个象限赋予一个2-bit值。例如,四个象限的2-bit值如下:

01  11

00  10

这些2-bit值 (00, 01, 10, 11) 分别代表了一个象限和在这个象限内的所有点。求解时,所有在左下角象限的点将会拥有geohash 00. 左上角象限的点的geohash会是 01 .依此类推,右下角和右上角的geohash分别是 1011

为了能更精确的索引,继续把每个象限划分为子象限。 每个子象限也一样会有geohash, 由父象限的geohash和子象限的geohash拼接在一起。右上角象限的geohash是 11 ,所以它的子象限的geohash将是(从左上开始,顺时针方向) 1101 , 1111 , 1110 , 和 1100

多个位置数据的文档的 2d 索引

2.0 新版功能: 支持在文档中存储多个位置

由于 2d 地理索引不支持在一篇文档中存储多个坐标集合, 您可以使用 多键索引 来索引在一篇文档中的多个坐标。举个最简单的例子, 您可能有某个键(例如 locs )存储这坐标数组, 如下:

{ _id : ObjectId(...),
  locs : [ [ 55.5 , 42.3 ] ,
           [ -74 , 44.74 ] ,
           { lng : 55.5 , lat : 42.3 } ]
}

数组中的元素坐标, 可以是数组形式, 如

您可以在 locs 键上创建一个地理索引如下:

db.places.ensureIndex( { "locs": "2d" } )

也许,您把位置数据建模为子文档中的一个键。在这种情况下,文档中应该有一个键(例如 addresses ) 存储了子文档数组, 其中每篇子文档都有一个键(例如 loc: )存储着位置坐标。如下:

{ _id : ObjectId(...),
  name : "...",
  addresses : [ {
                 context : "home" ,
                 loc : [ 55.5, 42.3 ]
                } ,
                {
                 context : "home",
                 loc : [ -74 , 44.74 ]
                }
              ]
}

那么, 您可以在 addresses.loc 键上创建地理索引,如下:

db.records.ensureIndex( { "addresses.loc": "2d" } )

geoNear 命令中,如果希望查询多位置文档时让距离数据和(生成该距离的)位置数据一起返回,请指定 includeLocs: true 选项。