• MongoDB CRUD操作:地理位置应用——通过地理空间查询查找餐厅


    MongoDB CRUD操作:地理位置应用——通过地理空间查询查找餐厅


    MongoDB通过对地理空间建立索引,可以对包含地理空间形状和点的集合上高效地执行空间查询,这边文章介绍了地理空间索引的的基本概念,介绍了地理空间查询的常用方法,演示了 $geoWithin$geoIntersects$nearSphere的使用。

    这里以一个App为例,介绍如何来帮助用户查找纽约市的餐厅。App完成的功能有:

    • 使用$geoIntersects查询用户的邻居
    • 使用$geoWithin显示社区的餐厅数量
    • 使用$nearSphere查找用户指定距离内的餐厅

    本文将使用2dsphere索引来查询有关球面几何的数据。

    地图的扭曲

    由于三维球体(例如地球)投影到平面上的原因,在地图上可视化时,球面几何形状会出现一定程度的扭曲。例如,采用由经纬度点 (0,0)、(80,0)、(80,80)和(0,80) 定义的球形正方形的规范。下图描绘了该区域所覆盖的区域:

    地图扭曲

    搜索餐厅

    在进行后续的操作前,需要先准备一些数据,需要先下载邻居neighborhoods餐厅restaurants的集合,并使用下面的命令将其导入数据库

    mongoimport restaurants.json -c=restaurants
    mongoimport neighborhoods.json -c=neighborhoods
    

    地理空间索引能在很大程度上提升$geoWithin$geoIntersects的查询性能,下面使用mongosh在对两个集合2dsphere索引:

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

    浏览数据

    查看mongosh中新创建的restaurants集合中的条目:

    db.restaurants.findOne()
    

    此查询返回下面的文档:

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

    餐厅对应的位置如下图所示:

    餐厅位置

    由于使用的是2dsphere索引,因此位置字段中的几何体数据必须遵循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"
    }
    

    数据对应下面的图形显示的区域:

    图形区域

    查找当前邻居

    如果用户的移动设备可以为用户提供准确的位置,那么使用$geoIntersects查找用户当前的邻居就很简单,
    假设用户位于经度-73.93414657、纬度40.82302903,要查找当前的邻居,需要使用GeoJSON格式的$geometry 字段指定一个点:

    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"
    }
    

    查找附近所有餐厅

    要查询给定区域中包含的所有餐厅,可以在mongosh中运行以下命令,可查询出所有餐厅,并计算该社区内的餐厅数量:

    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返回无序结果,或者使用$nearSphere$maxDistance(如需要按距离排序)。

    使用$geoWithin,不排序

    要查找圆形区域内的餐厅,可使用$geoWithin$centerSphere$centerSphere是MongoDB特有的语法,通过指定中心和半径(以弧度为单位)来表示圆形区域。

    $geoWithin不会按任何特定顺序返回文档,因此它可能会先向用户显示最远的文档。下面的示例查找距离用户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 } } })
    
  • 相关阅读:
    基于FPGA的IIR滤波器的实现(1)— MATLAB函数实现
    干货︱部分领域数字孪生白皮书及报告汇总(附下载)
    国内免费版ChatGPT
    Swagger2使用------------整合SpringBoot
    Ubuntu系统中tree的用法
    C# .NET6 Log4net输出日志
    Java基础——面向对象(复习)
    面试面经|Java面试基础题17道
    通过termux tailscale huggingface 来手把手一步一步在手机上部署LLAMA2-7b和LLAMA2-70b大模型
    stm32-----定时中断基本结构
  • 原文地址:https://blog.csdn.net/superatom01/article/details/139454938