目录
进入MongoDB中文手册(4.2版本)目录
MongoDB支持对地理空间数据的查询操作。本章节介绍MongoDB的地理空间特性。
1 地理空间数据
MongoDB中,您可以将地理空间数据存储为GeoJSON对象或传统坐标对( legacy coordinate pairs)。
1.1 GeoJSON对象
要在类似地球的球体上计算几何形状,请将位置数据存储为GeoJSON对象。
要指定GeoJSON数据,请使用具有以下内容的嵌入式文档:
- 一个GeoJSON对象类型的命名为type的字段;
- 以及一个指定对象坐标的coordinates字段。
如果指定纬度和经度坐标,请先列出经度(longitude ),然后再列出纬度(纬度)- 有效的经度值介于-180和之间180,并且包括-180和180;
- 有效的纬度值介于-90和之间90,并且包括-90和90。
<field>: { type: <GeoJSON type> , coordinates: <coordinates> }
例如,要指定一个GeoJSON坐标点(GeoJSON Point):
location: {
type: "Point",
coordinates: [-73.856077, 40.848447]
}
有关MongoDB支持的GeoJSON对象的列表以及示例,请参阅GeoJSON对象。
对GeoJSON对象的MongoDB地理空间查询是在球体上计算的;MongoDB使用WGS84参考系统对GeoJSON对象进行地理空间查询。
1.2 传统坐标对(Legacy Coordinate Pairs)
要计算欧几里得平面(Euclidean plane)上的距离,请将您的位置数据存储为传统坐标对并使用2d索引。通过将数据转换为GeoJSON Point类型,MongoDB支持通过2dsphere索引对传统坐标对进行球面计算。
要将数据指定为传统坐标对,可以使用数组(首选)或嵌入式文档。
通过数组指定(首选):
<field>: [ <x>, <y> ]
如果指定纬度和经度坐标,请先列出经度,然后再列出维度;即
<field>: [<longitude>, <latitude> ]
- 有效的经度值介于-180和之间180,并且包括-180和180;
- 有效的纬度值介于-90和之间90,并且包括-90和90。
通过嵌入式文档指定:
<field>: { <field1>: <x>, <field2>: <y> }
如果指定纬度和经度坐标,则第一个字段(无论字段名称如何)都必须包含经度值,第二个字段必须包含纬度值;即
<field>: { <field1>: <longitude>, <field2>: <latitude> }
- 有效的经度值介于-180和之间180,并且包括-180和180;
- 有效的纬度值介于-90和之间90,并且包括-90和90。
对于指定传统坐标对,数组优先于嵌入式文档,因为某些语言不保证关联地图的排序。
2 地理空间索引
MongoDB提供以下地理空间索引类型来支持地理空间查询。
2.1 2dsphere
2dsphere索引支持查询,该查询可计算类似地球的球体上的几何形状。
要创建2dsphere索引,请使用 db.collection.createIndex()方法并指定字符串"2dsphere"作为索引类型:
db.collection.createIndex( { <location field> : "2dsphere" } )
其中,是一个字段,其值可以是 GeoJSON对象或传统坐标对。
有关2dsphere索引的更多信息,请参见2dsphere索引。
2.2 2d
2d索引支持的查询,可计算二维平面的几何 。尽管索引可以支持$nearSphere的查询是在球体上进行计算,但如果可能,请对球面查询使用2dsphere索引。
要创建2d索引,请使用db.collection.createIndex() 方法,将位置字段指定为键,并将字符串"2d"指定为索引类型:
db.collection.createIndex( { <location field> : "2d" } )
其中,是一个字段,其值为传统坐标对。
有关2d索引的更多信息,请参见2d索引。
2.3 地理空间索引和分片集合
分片集合时,不能将地理空间索引用作分片键。但是,可以通过使用其他字段作为分片键在分片集合上创建地理空间索引。
分片集合支持以下地理空间操作:
- $geoNear 聚合阶段;
- $near和$nearSphere查询运算符(从MongoDB 4.0开始。
开始在MongoDB中4.0,$near和$nearSphere查询都支持分片集合。
在早期版本的MongoDB,$near和$nearSphere查询不支持分片的集合; 相反,对于分片群集,必须使用$geoNear聚合阶段或geoNear命令(在MongoDB 4.0及更低版本中可用)。
您还可以使用$geoWithin和$geoIntersect查询分片群集的地理空间数据 。
2.4 覆盖查询(Covered Queries)
3 地理空间查询
注意
对于球形查询,请使用2dsphere索引结果。
将2d索引用于球形查询可能会产生错误的结果,例如将2d索引用于环绕两极的球形查询。
3.1 地理空间查询运算符
MongoDB提供以下地理空间查询运算符:
名称 | 描述 |
---|---|
$geoIntersects | 选择与GeoJSON几何形状相交的几何形状。2dsphere索引支持$geoIntersects。 |
$geoWithin | 选择边界GeoJSON几何内的几何。2dsphere和2D索引支持$geoWithin。 |
$near | 返回点附近的地理空间对象。需要地理空间索引。2dsphere和2D索引支持$near。 |
$nearSphere | 返回球体上某个点附近的地理空间对象。需要地理空间索引。2dsphere和2D索引支持 $nearSphere。 |
有关更多详细信息(包括示例),请参见各个参考页。
3.2 地理空间聚合阶段
阶段 | 描述 |
---|---|
$geoNear | 根据与地理空间点的接近程度返回有序的文档流。包含用于地理空间数据的$match,$sort和$limitd的功能。输出文档包括一个附加距离字段,并且可以包括位置唯一标识的字段。 $geoNear需要地理空间索引。 |
有关更多详细信息(包括示例),请参见$geoNear 参考页。
4 地理空间模型
MongoDB地理空间查询可以解释平面或球体上的几何。
2dsphere 索引仅支持球形查询(即解释球形表面几何形状的查询)。
2d索引支持平面查询(即解释平面上的几何形状的查询)和一些球形查询。虽然2d 索引支持某些球形查询,但2d对这些球形查询使用索引可能会导致错误。如果可能,将 2dsphere索引用于球形查询。
下表列出了每个地理空间操作所使用和支持的地理空间查询运算符:
操作 | 球面(Spherical)查询/平面(Flat)查询 | 备注 |
---|---|---|
$near(此行和下一行的GeoJSON中心心点,2dsphere索引) | 球形 | 另请参阅$nearSphere运算符,该运算符与GeoJSON和2dsphere索引一起使用时提供相同的功能。 |
$near(传统坐标,2d索引) | 平面 | |
$nearSphere(GeoJSON点,2dsphere索引) | 球形 | 提供与使用GeoJSON点和 2dsphere索引的$near操作相同的功能。 对于球形查询,最好使用 $nearSphere而不是$near, $nearSphere运算符显式指定球形查询的名称。 |
$nearSphere(传统坐标) | 球形 | 请改用GeoJSON点。 |
$geoWithin:{ $geometry:…} | 球形 | |
$geoWithin:{ $box:…} | 平面 | |
$geoWithin:{ $polygon:…} | 平面 | |
$geoWithin:{ $center:…} | 平面 | |
$geoWithin:{ $centerSphere:…} | 球形 | |
$geoIntersects | 球形 | |
$geoNear聚合阶段(2dsphere索引) | 球形 | |
$geoNear聚合阶段(2d索引) | 平面 |
5 示例
使用以下文档创建一个places集合:
db.places.insert( {
name: "Central Park",
location: { type: "Point", coordinates: [ -73.97, 40.77 ] },
category: "Parks"
} );
db.places.insert( {
name: "Sara D. Roosevelt Park",
location: { type: "Point", coordinates: [ -73.9928, 40.7193 ] },
category: "Parks"
} );
db.places.insert( {
name: "Polo Grounds",
location: { type: "Point", coordinates: [ -73.9375, 40.8303 ] },
category: "Stadiums"
} );
以下操作在位置(location)字段上创建2dsphere索引 :
db.places.createIndex( { location: "2dsphere" } )
以下查询使用$near运算符返回距指定GeoJSON点至少1000米,最多5000米的文档,并按从最近到最远的顺序排序:
db.places.find(
{
location:
{ $near:
{
$geometry: { type: "Point", coordinates: [ -73.9667, 40.78 ] },
$minDistance: 1000,
$maxDistance: 5000
}
}
}
)
下操作使用geoNear聚合操作返回与查询过滤器{ category: “Parks” }匹配的文档,该文档按距指定GeoJSON点最近到最远的顺序排序:
db.places.aggregate( [
{
$geoNear: {
near: { type: "Point", coordinates: [ -73.9667, 40.78 ] },
spherical: true,
query: { category: "Parks" },
distanceField: "calcDistance"
}
}
] )