寻找地理空间查询的餐厅

在本页面

概观

MongoDB 的地理空间索引允许您在包含地理空间形状和点的集合上有效地执行空间查询。本教程将简要介绍地理空间索引的概念,然后演示它们与$geoWithin$geoIntersectsgeoNear的使用。

为了展示地理空间 features 的功能并比较不同的方法,本教程将指导您完成为简单的地理空间应用程序编写查询的 process。

假设您正在设计移动应用程序以帮助用户在纽约市找到餐馆。 application 必须:

本教程将使用2dsphere索引来查询球形几何体上的此数据。

有关球面和平面几何的更多信息,请参阅地理空间模型

失真

由于将三维球体(例如地球)投射到平面上的性质,球形几何体在 map 上可视化时将显得扭曲。

例如,采用由经度纬度点(0,0)(80,0)(80,80)(0,80)定义的球形正方形的规格。下图描绘了该地区所涵盖的区域:

投射到球形上的正方形的图。

寻找餐馆

先决条件

https://raw.githubusercontent.com/mongodb/docs-assets/geospatial/neighborhoods.jsonhttps://raw.githubusercontent.com/mongodb/docs-assets/geospatial/restaurants.json下载 example 数据集。它们分别包含集合restaurantsneighborhoods

下载数据集后,将它们导入数据库:

mongoimport <path to restaurants.json> -c restaurants
mongoimport <path to neighborhoods.json> -c neighborhoods

geoNear命令需要地理空间索引,并且几乎总能改进$geoWithin$geoIntersects查询的 performance。

因为此数据是地理数据,所以使用mongo shell 在每个集合上创建2dsphere索引:

db.restaurants.createIndex({ location: "2dsphere" })
db.neighborhoods.createIndex({ geometry: "2dsphere" })

探索数据

检查mongo shell 中 newly-created restaurants集合中的条目:

db.restaurants.findOne()

此查询返回如下文档:

{
   location: {
      type: "Point",
      coordinates: [-73.856077, 40.848447]
   },
   name: "Morris Park Bake Shop"
}

此餐厅文档对应于下图中显示的位置:

单个地理空间点的地图。

由于本教程使用2dsphere索引,因此location字段中的几何数据必须遵循GeoJSON 格式

现在检查neighborhoods集合中的条目:

db.neighborhoods.findOne()

此查询将_return 返回如下文档:

{
   geometry: {
      type: "Polygon",
      coordinates: [[
         [ -73.99, 40.75 ],
         ...
         [ -73.98, 40.76 ],
         [ -73.99, 40.75 ]
      ]]
    },
    name: "Hell's Kitchen"
}

此几何对应于下图中描绘的区域:

地理空间多边形的地图。

找到当前社区

假设用户的移动设备可以为用户提供合理准确的位置,则很容易找到用户的当前邻居$geoIntersects

假设用户位于-73.93414657 经度和 40.82302903 纬度。要查找当前邻域,您将使用以 GeoJSON格式的特殊$geometry字段指定一个点:

db.neighborhoods.findOne({ geometry: { $geoIntersects: { $geometry: { type: "Point", coordinates: [ -73.93414657, 40.82302903 ] } } } })

此查询将_return 以下结果:

{
    "_id" : ObjectId("55cb9c666c522cafdb053a68"),
    "geometry" : {
        "type" : "Polygon",
        "coordinates" : [
            [
                [
                    -73.93383000695911,
                    40.81949109558767
                ],
                ...
            ]
        ]
    },
    "name" : "Central Harlem North-Polo Grounds"
}

寻找邻里的所有餐厅

您还可以查询以查找给定社区中包含的所有餐馆。 在mongo shell 中运行以下内容以查找包含用户的邻域,然后计算该邻域内的餐馆:

var neighborhood = db.neighborhoods.findOne( { geometry: { $geoIntersects: { $geometry: { type: "Point", coordinates: [ -73.93414657, 40.82302903 ] } } } } )
db.restaurants.find( { location: { $geoWithin: { $geometry: neighborhood.geometry } } } ).count()

此查询将告诉您所请求的邻域中有 127 家餐厅,如下图所示:

地理空间多边形中所有餐馆的地图。

查找距离内的餐馆

要在点的指定距离内查找餐馆,您可以使用$geoWithin$centerSphere来 return 结果未排序 order,或nearSphere$maxDistance如果您需要按距离排序的结果。

用$geoWithin 未排序

要查找圆形区域内的餐馆,请使用$geoWithin$centerSphere$centerSphere是 MongoDB-specific 语法,通过以弧度为单位指定中心和半径来表示圆形区域。

$geoWithin不会_return 任何特定 order 中的文档,因此它可以首先向用户显示最远的文档。

以下将找到距离用户 5 英里范围内的所有餐厅:

db.restaurants.find({ location:
   { $geoWithin:
      { $centerSphere: [ [ -73.93414657, 40.82302903 ], 5 / 3963.2 ] } } })

$centerSphere的第二个参数以弧度为单位接受半径,因此必须将其除以地球半径(以英里为单位)。有关在距离单位之间进行转换的更多信息,请参见使用球面几何计算距离

用$nearSphere 排序

您也可以使用$nearSphere并以米为单位指定$maxDistance术语。这将返回用户 5 英里内的所有餐厅,从最近到最远的排序订单:

var METERS_PER_MILE = 1609.34
db.restaurants.find({ location: { $nearSphere: { $geometry: { type: "Point", coordinates: [ -73.93414657, 40.82302903 ] }, $maxDistance: 5 * METERS_PER_MILE } } })
Updated at: 7 months ago
地理空间查询Table of contentGeoJSON Objects