使用球面几何计算距离¶
On this page
注解
虽然 2d 索引支持在基本查询中使用球面距离,您可以考虑转换到 2dsphere 索引,如果您的数据都是经度和纬度。
MongoDB在 2d 索引支持在欧几里德平面上计算距离的查询。该类索引还支持如下使用球面几何来计算距离的索引操作符和命令:
- $nearSphere
- $centerSphere
- $near
带有 { spherical: true } 选项的 geoNear 。
重要
These three queries use radians for distance. Other query types do not.
为了确保球面操作符能计算正确,您必须将距离转换成弧度,以及将弧度转换为距离,单位是您的应用所需要的单位。
转换如下:
从距离到弧度: 将距离除以球面的半径(例如地球半径),两者单位一致。
从弧度到距离:将弧度乘以球面半径(例如地球半径),单位换算成您所希望使用的单位。
The equatorial radius of the Earth is approximately 3,963.2 miles or 6,378.1 kilometers.
如下查询会从 places 集合中返回在圆内部的文档,这个圆的圆心是 [ -74, 40.74 ] ,半径是 100 。
db.places.find( { loc: { $geoWithin: { $centerSphere: [ [ -74, 40.74 ] ,
100 / 3963.2 ] } } } )
您也可以在 geoNear 中使用 distanceMultiplier 选项,在 mongod 程序中将弧度转换为距离。而不是在您的应用代码中。参见 distance multiplier 。
如下球面查询会返回 places 集合中距离点 [ -74, 40.74 ] 有 100 英里的所有文档。
db.runCommand( { geoNear: "places",
near: [ -74, 40.74 ],
spherical: true
} )
以上的输出如下:
{
// [ ... ]
"results" : [
{
"dis" : 0.01853688938212826,
"obj" : {
"_id" : ObjectId( ... )
"loc" : [
-73,
40
]
}
}
],
"stats" : {
// [ ... ]
"avgDistance" : 0.01853688938212826,
"maxDistance" : 0.01853714811400047
},
"ok" : 1
}
警告
球面查询中的条件如果环绕着南/北极或者在 -180 到 180 经度的交界过渡区,会导致错误。
注解
虽然地理索引的默认的类地球面边界是大于等于 -180 到小于 180 间,纬度的合理值却是在 -90 到 90 间。
距离系数 - Distance Multiplier¶
带有 distanceMultiplier 选项的 geoNear 命令可以在将结果和给定值相乘后再返回。这可以让MongDB返回转换后的值,免除了在应用逻辑中转换单位的需要。
在球面查询中使用 distanceMultiplier 会返回和 geoNear 命令相同的结果,都不需要弧度-到-距离的转换。如下示例中,在 geoNear 命令中使用 distanceMultiplier 和 spherical 参数:
db.runCommand( { geoNear: "places",
near: [ -74, 40.74 ],
spherical: true,
distanceMultiplier: 3963.2
} )
The output of the above operation would resemble the following:
{
// [ ... ]
"results" : [
{
"dis" : 73.46525170413567,
"obj" : {
"_id" : ObjectId( ... )
"loc" : [
-73,
40
]
}
}
],
"stats" : {
// [ ... ]
"avgDistance" : 0.01853688938212826,
"maxDistance" : 0.01853714811400047
},
"ok" : 1
}