使用球面几何计算距离

在本页面

Note

虽然2d索引支持使用球面距离的基本查询,但是如果您的数据主要是经度和纬度,请考虑移至2dsphere索引。

2d索引支持用于计算欧几里得平面(平坦表面)上的距离的查询。该索引还支持以下查询运算符和命令,这些运算符和命令使用球形几何体计算距离:

Important

这三个查询使用弧度表示距离。其他查询类型则不。

为了使球形查询运算符正常运行,必须将距离转换为弧度,并将弧度转换为应用程序使用的距离单位。

To convert:

  • 到弧度的距离:以与距离测量相同的单位将距离除以球体(例如地球)的半径。

  • 弧度到距离:将弧度测量值乘以要转换距离的单位制中球体(例如地球)的半径。

地球的赤道半径约为3,963.2英里或6,378.1公里。

以下查询将返回中心[ -74, 40.74 ]所描述的半径为100英里的圆圈内的places集合中的文档:

db.places.find( { loc: { $geoWithin: { $centerSphere: [ [ -74, 40.74 ] ,
                                                     100 / 3963.2 ] } } } )

您也可以在geoNear中使用distanceMultiplier选项,以在mongod进程中而不是在应用程序代码中转换弧度。参见distance multiplier

以下球形查询返回距离点[ -74, 40.74 ] 100英里内的集合places中的所有文档。

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
}

Warning

对于球形查询,请使用2dsphere索引结果。

对于球形查询使用2d索引可能会导致错误的结果,例如对于围绕极点的球形查询使用2d索引。

Note

如果指定纬度和经度坐标,请先列出 经度 ,然后列出 latitude

  • 有效的经度值在-180180之间(包括两端值)。

  • 有效的纬度值在-9090之间(包括两端值)。

Distance Multiplier

geoNear命令的distanceMultiplier选项仅在将结果乘以指定的值后才返回距离。这使 MongoDB 可以返回转换后的值,并消除了在应用程序逻辑中转换单位的要求。

在球形查询中使用distanceMultiplier可以提供来自geoNear命令的结果,这些结果不需要弧度到距离的转换。以下示例在geoNear命令中使用distanceMultiplier,并以spherical示例使用:

db.runCommand( { geoNear: "places",
                 near: [ -74, 40.74 ],
                 spherical: true,
                 distanceMultiplier: 3963.2
               }  )

以上操作的输出类似于以下内容:

{
   // [ ... ]
   "results" : [
      {
         "dis" : 73.46525170413567,
         "obj" : {
            "_id" : ObjectId( ... )
            "loc" : [
               -73,
               40
            ]
         }
      }
   ],
   "stats" : {
      // [ ... ]
      "avgDistance" : 0.01853688938212826,
      "maxDistance" : 0.01853714811400047
   },
   "ok" : 1
}