Find Restaurants with Geospatial Queries使用地理空间查询查找餐厅

On this page本页内容

Overview概述

MongoDB’s geospatial indexing allows you to efficiently execute spatial queries on a collection that contains geospatial shapes and points. MongoDB的地理空间索引允许您高效地对包含地理空间形状和点的集合执行空间查询。To showcase the capabilities of geospatial features and compare different approaches, this tutorial will guide you through the process of writing queries for a simple geospatial application.为了展示地理空间功能的功能并比较不同的方法,本教程将指导您完成为简单的地理空间应用程序编写查询的过程。

This tutorial will briefly introduce the concepts of geospatial indexes, and then demonstrate their use with $geoWithin, $geoIntersects, and $nearSphere.本教程将简要介绍地理空间索引的概念,然后用$geoWithin$geoIntersectsS和$nearSphere演示它们的用法。

Suppose you are designing a mobile application to help users find restaurants in New York City. 假设您正在设计一个移动应用程序,帮助用户在纽约市找到餐馆。The application must:申请必须:

This tutorial will use a 2dsphere index to query for this data on spherical geometry.本教程将使用2dsphere索引来查询球面几何体上的这些数据。

For more information on spherical and flat geometries, see Geospatial Models.有关球形和平面几何图形的详细信息,请参阅地理空间模型

Distortion扭曲

Spherical geometry will appear distorted when visualized on a map due to the nature of projecting a three dimensional sphere, such as the earth, onto a flat plane.由于将三维球体(如地球)投影到平面上的性质,在地图上可视化时,球形几何体会出现扭曲。

For example, take the specification of the spherical square defined by the longitude latitude points (0,0), (80,0), (80,80), and (0,80). 例如,以经纬度点(0,0)(80,0)(80,80)(0,80)定义的球面正方形的规格为例。The following figure depicts the area covered by this region:下图描述了该区域所覆盖的区域:

Diagram of a square projected onto a sphere.

Searching for Restaurants寻找餐馆

Prerequisites先决条件

Download the example datasets from https://raw.githubusercontent.com/mongodb/docs-assets/geospatial/neighborhoods.json and https://raw.githubusercontent.com/mongodb/docs-assets/geospatial/restaurants.json. These contain the collections restaurants and neighborhoods respectively.

After downloading the datasets, import them into the database:下载数据集后,将其导入数据库:

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

A geospatial index, and almost always improves performance of $geoWithin and $geoIntersects queries.

Because this data is geographical, create a 2dsphere index on each collection using the mongo shell:

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

Exploring the Data探索数据

Inspect an entry in the newly-created restaurants collection from within the mongo shell:mongo shell中查看新创建的restaurants集合中的一个条目:

db.restaurants.findOne()

This query returns a document like the following:此查询返回如下文档:

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

This restaurant document corresponds to the location shown in the following figure:本餐厅文件对应于下图所示的位置:

Map of a single geospatial point.

Because the tutorial uses a 2dsphere index, the geometry data in the location field must follow the GeoJSON format.

Now inspect an entry in the neighborhoods collection:现在检查neighborhoods集合中的一个条目:

db.neighborhoods.findOne()

This query will return a document like the following:此查询将返回如下文档:

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

This geometry corresponds to the region depicted in the following figure:该几何体对应于下图所示的区域:

Map of a geospatial polygon.

Find the Current Neighborhood找到当前社区

Assuming the user’s mobile device can give a reasonably accurate location for the user, it is simple to find the user’s current neighborhood with $geoIntersects.假设用户的移动设备可以为用户提供一个合理准确的位置,用$geoIntersects查找用户的当前邻居就很简单了。

Suppose the user is located at -73.93414657 longitude and 40.82302903 latitude. 假设用户位于-73.93414657经度和40.82302903纬度。To find the current neighborhood, you will specify a point using the special $geometry field in GeoJSON format:

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

This query will return the following result:此查询将返回以下结果:

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

Find all Restaurants in the Neighborhood找到附近所有的餐馆

You can also query to find all restaurants contained in a given neighborhood. 您还可以查询以查找给定社区中包含的所有餐厅。Run the following in the mongo shell to find the neighborhood containing the user, and then count the restaurants within that neighborhood: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()

This query will tell you that there are 127 restaurants in the requested neighborhood, visualized in the following figure:此查询将告诉您,请求的社区中有127家餐厅,如下图所示:

Map of all restaurants in a geospatial polygon.

Find Restaurants within a Distance在附近找餐馆

To find restaurants within a specified distance of a point, you can use either $geoWithin with $centerSphere to return results in unsorted order, or nearSphere with $maxDistance if you need results sorted by distance.

Unsorted with $geoWithin使用$geoWithin不排序

To find restaurants within a circular region, use $geoWithin with $centerSphere. $centerSphere is a MongoDB-specific syntax to denote a circular region by specifying the center and the radius in radians.$centerSphere是MongoDB特有的语法,通过以弧度为单位指定圆心和半径来表示圆形区域。

$geoWithin does not return the documents in any specific order, so it may show the user the furthest documents first.$geoWithin不会以任何特定顺序返回文档,因此它可能会首先向用户显示最远的文档。

The following will find all restaurants within five miles of the user:以下内容将显示距离用户5英里以内的所有餐厅:

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

$centerSphere’s second argument accepts the radius in radians, so you must divide it by the radius of the earth in miles. $centerSphere的第二个参数接受以弧度为单位的半径,因此必须将其除以以英里为单位的地球半径。See Calculate Distance Using Spherical Geometry for more information on converting between distance units.有关在距离单位之间转换的详细信息,请参阅使用球面几何体计算距离

Sorted with $nearSphere使用$nearSphere排序

You may also use $nearSphere and specify a $maxDistance term in meters. 您还可以使用$nearSphere并以米为单位指定$maxDistance项。This will return all restaurants within five miles of the user in sorted order from nearest to farthest:这将按从最近到最远的顺序返回用户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 } } })