通过地理空间查询餐厅


进入MongoDB中文手册(4.2版本)目录

1 概述

MongoDB的地理空间索引使您可以高效地对包含地理空间形状和点的集合执行空间查询。为了展示地理空间特性的能力并比较不同的方法,本教程将指导您完成一个简单的地理空间查询的应用程序的编写。
本教程将简要介绍地理空间索引的概念,然后通过$geoWithin, $geoIntersects和$nearSphere展示它们的使用。
假设您正在设计一个移动应用程序,以帮助用户找到纽约市的餐馆。该应用程序必须:

  • 通过$geoIntersects确定用户当前的附近地区,
  • 使用$geoWithin显示附近的餐厅数量,
  • 并且使用$nearSphere查找在用户指定距离内的餐厅 。
    本教程将使用2dsphere索引来查询有关球形几何的数据。
    有关球面和平面几何的更多信息,请参见地理空间模型(Geospatial Models)

2 失真

当将三维球体(例如地球)投影到平面上,并在地图上显示时,球形几何形状将失真。
例如,下图描绘了被经度纬度点(0,0),(80,0),(80,80),和 (0,80)确定的球面正方形(spherical square)覆盖的区域:
在这里插入图片描述

3 搜索餐厅

3.1 前提条件


https://raw.githubusercontent.com/mongodb/docs-assets/geospatial/restaurants.json下载示例数据集 。他们分别包含restaurants和neighborhoods集合。
下载数据集后,将它们导入数据库:

mongoimport <restaurants.json的路径> -c=restaurants
mongoimport <neighborhoods.json的路径> -c=neighborhoods

地理空间索引,几乎总是可以提高 g e o W i t h i n 和 geoWithin和 geoWithingeoIntersects 查询的性能。
由于此数据是地理数据,因此请使用mongoShell在每个集合上创建2dsphere索引:

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

3.2 查找数据

在mongo shell中检查新创建的restaurants集合中的条目:

db.restaurants.findOne()

该查询返回如下文档:

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

该餐厅文档对应下图所示的位置:
在这里插入图片描述
由于本教程使用2dsphere索引,因此location字段中的几何数据 必须遵循GeoJSON格式。
现在检查neighborhoods集合中的条目:

db.neighborhoods.findOne()

该查询将返回如下文档:

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

该几何形状对应于下图所示的区域:
在这里插入图片描述

3.3 找到当前Neighborhood

假设用户的移动设备可以为用户提供合理准确的位置,则使用 g e o I n t e r s e c t s 即 可 轻 松 找 到 用 户 的 当 前 n e i g h b o r h o o d 。 假 设 用 户 位 于 经 度 − 73.93414657 和 纬 度 40.82302903 。 要 找 到 当 前 n e i g h b o r h o o d , 您 将 使 用 G e o J S O N 格 式 的 geoIntersects即可轻松找到用户的当前neighborhood 。 假设用户位于经度-73.93414657和纬度40.82302903。要找到当前neighborhood ,您将使用GeoJSON格式的 geoIntersectsneighborhood73.9341465740.82302903neighborhood使GeoJSONgeometry字段指定一个点 :

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

该查询将返回以下结果:

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

3.4 找到Neighborhood中的所有餐馆

您还可以查询到给定neighborhood中包含的所有餐馆。在mongo shell中运行以下命令,找到包含用户的neighborhood,然后对neighborhood中的餐馆计数:

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家餐厅,如下图所示:
在这里插入图片描述

3.5 找到一定距离范围内的餐馆

要找到一个点的指定距离内的餐馆,您可以使用$geoWithin与$centerSphere返回在未排序结果,或如果您需要的结果要按距离排序则使用$nearSphere与$maxDistance。

3.6 使用$geoWithin不排序

使用$geoWithin与$centerSphere可以一个圆形区域内找到餐馆。$centerSphere是MongoDB特定的语法,用于指定弧度的中心和半径来表示圆形区域。
$geoWithin不会以任何特定顺序返回文档,因此它可能首先向用户显示最远的文档。
以下内容将查找距用户五英里范围内的所有餐馆:

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

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

3.7 使用$nearSphere排序

您也可以使用$nearSphere并以米为单位指定$maxDistance。示例中将以从近到远的排序顺序返回距离用户五英里以内的所有餐厅:

var METERS_PER_MILE = 1609.34
db.restaurants.find({ location: { $nearSphere: { $geometry: { type: "Point", coordinates: [ -73.93414657, 40.82302903 ] }, $maxDistance: 5 * METERS_PER_MILE } } })


进入MongoDB中文手册(4.2版本)目录

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值