• MongoDB CRUD操作:地理位置查询


    MongoDB CRUD操作:地理位置查询


    MongoDB支持地理空间数据的查询,这是MongoDB数据库有别于其它数据库的特色之一,在进行GIS相关系统开发的时候会比较有帮助。本文重点介绍MongoDB的地理空间功能。

    gis search

    地理空间数据

    在MongoDB中,可以将地理空间数据存储为GeoJSON对象或传统坐标对。

    GeoJSON对象

    要计算类地球体上的几何形状,可将位置数据存储为GeoJSON对象,GeoJSON对象是一个内嵌文档:

    • 名为 type 的字段,指定 GeoJSON对象类型
    • 名为坐标的字段,用于指定对象的坐标。
    <field>: { type: <GeoJSON type> , coordinates: <coordinates> }
    

    注意:

    经纬度坐标的第一个元素是经度第二个元素是纬度。其中经度值介于-180和180之间(含)。有效的纬度值介于-90和90之间(含)。

    例如,一个GeoJSON的点:

    location: {
          type: "Point",
          coordinates: [-73.856077, 40.848447]
    }
    

    关于对GeoJSON对象的地理空间查询在球体上计算,MongoDB 使用WGS84参考系统对GeoJSON对象进行地理空间查询。

    传统坐标对

    要计算欧几里得平面上的距离,需将位置数据存储为传统坐标对并使用2d索引。如果手动将数据转换为GeoJSON点类型,MongoDB将通过使用2dsphere索引支持传统坐标对上的球面计算。

    要将数据指定为传统坐标对,可以使用数组(首选)或嵌入式文档。

    通过数组指定(首选)
    <field>: [ <x>, <y> ]
    

    指定经纬度坐标时,则指定经度,再指定纬度。

    <field>: [<longitude>, <latitude> ]
    
    • 有效的经度值介于 -180 和 180 之间(包含)。
    • 有效的纬度值介于 -90 和 90 之间(包含)。
    通过嵌入文档指定
    <field>: { <field1>: <x>, <field2>: <y> }
    

    如果指定纬度和经度坐标,则无论字段名称如何,第一个字段都必须包含经度值,第二个字段必须包含纬度值,即:

    <field>: { <field1>: <longitude>, <field2>: <latitude> }
    
    • 有效的经度值介于 -180 和 180 之间(包含)。
    • 有效的纬度值介于 -90 和 90 之间(包含)。

    指定旧坐标对,数组优于嵌入文档,因为某些语言不保证关联映射顺序。

    地理空间索引

    MongoDB 提供以下地理空间索引类型来支持地理空间查询:

    2dsphere

    2dsphere 索引支持计算类地球体几何图形的查询。

    可使用db.collection.createIndex()创建2dsphere索引,并指定字符串"2dsphere"作为索引类型:

    db.collection.createIndex( { <location field> : "2dsphere" } )
    

    其中,是一个字段,其值为GeoJSON对象或传统坐标对。

    **注意:**在包含geoJSON点数组的字段上创建索引,将失败并返回错误信息:MongoServerError:索引构建失败

    2d

    2d索引支持在二维平面几何图形的查询,虽然2d索引可以支持在球面上的$nearSphere查询,但还是建议尽量使用2dsphere索引进行球面查询。

    可使用db.collection.createIndex()创建2dsphere索引,并指定字符串"2d"作为索引类型:

    db.collection.createIndex( { <location field> : "2d" } )
    

    字段的值是一个传统坐标对。

    地理空间查询

    注意:使用二维索引查询球形数据可能会返回不正确的结果或错误。例如,二维索引不支持围绕极点的球形查询。

    地理空间查询运算符

    MongoDB 提供以下地理空间查询操作符:

    运算符描述
    $geoIntersects选择与GeoJSON几何图形相交的几何图形。2dsphere索引支持 $geoIntersects
    $geoWithin在边界 GeoJSON 几何图形中选择几何图形。2dsphere 和 2d 索引都支持 $geoWithin
    $near返回靠近某个点的地理空间对象。需要地理空间索引。 2dsphere 和 2d 索引都支持$near
    $nearSphere返回球体上某个点附近的地理空间对象。需要地理空间索引。 2dsphere 和 2d 索引都支持 $nearSphere

    地理空间聚合阶段

    MongoDB支持$geoNear地理空间聚合管道阶段,可根据与地理空间点的接近程度返回有序的文档流,合并了地理空间数据的$match$sort$limit 的功能,输出文档包括附加距离字段,并且可以包括位置标识符字段。$geoNear要求地理空间索引。

    地理空间模型

    MongoDB 地理空间查询可解释平面或球面上的几何图形,2dsphere索引只支持球面查询(即解释球面上几何图形的查询),2d索引支持平面查询(即解释平面上几何图形的查询)和部分球面查询,虽然 2d 索引支持某些球面查询,但在这些球面查询中使用2d索引可能会导致错误。所以,建议尽量使用 2dsphere 索引进行球形查询。

    下表列出了每个地理空间操作使用的地理空间查询操作符、支持的查询:

    操作球形/平面查询说明
    $near(本行和下一行的GeoJSON质心点,2dsphere索引)球形参考$nearSphere运算符,它在与 GeoJSON 和 2dsphere 索引一起使用时提供相同的功能
    $near(传统坐标,2D 索引)平面
    $nearSphere(GeoJSON 点,2dsphere 索引)球形提供与使用 GeoJSON点和2dsphere索引的$near操作相同的功能。对于球形查询,最好使用$nearSphere,在名称中显式指定球形查询,而不是$near运算符
    $nearSphere(传统坐标,2d索引)球面使用GeoJSON替代
    $geoWithin : { $geometry: ... }球面
    $geoWithin : { $box: ... }平面
    $geoWithin : { $polygon: ... }平面
    $geoWithin : { $center: ... }平面
    $geoWithin : { $centerSphere: ... }球面
    $geoIntersects球面
    $geoNear聚合阶段(2dsphere索引)球面
    $geoNear聚合阶段(2d索引))平面

    举例

    使用下面的脚本创建places集合:

    db.places.insertMany( [
       {
          name: "Central Park",
          location: { type: "Point", coordinates: [ -73.97, 40.77 ] },
          category: "Parks"
       },
       {
          name: "Sara D. Roosevelt Park",
          location: { type: "Point", coordinates: [ -73.9928, 40.7193 ] },
          category: "Parks"
       },
       {
          name: "Polo Grounds",
          location: { type: "Point", coordinates: [ -73.9375, 40.8303 ] },
          category: "Stadiums"
       }
    ] )
    

    先在location字段上创建2dsphere索引:

    db.places.createIndex( { location: "2dsphere" } )
    

    下面的查询使用$near运算符返回距离指定GeoJSON点至少1000米、最多 5000米的文档,并按从最近到最远的顺序排序:

    db.places.find(
       {
         location:
           { $near:
              {
                $geometry: { type: "Point",  coordinates: [ -73.9667, 40.78 ] },
                $minDistance: 1000,
                $maxDistance: 5000
              }
           }
       }
    )
    

    下面的操作使用$geoNear聚合操作返回与查询过滤器{category: "Parks" }匹配的文档,并按照距指定GeoJSON点从最近到最远的顺序排序:

    db.places.aggregate( [
       {
          $geoNear: {
             near: { type: "Point", coordinates: [ -73.9667, 40.78 ] },
             spherical: true,
             query: { category: "Parks" },
             distanceField: "calcDistance"
          }
       }
    ] )
    
  • 相关阅读:
    Flink kafka 数据汇不指定分区器导致的问题
    【吴恩达机器学习笔记】五、逻辑回归
    ​LeetCode解法汇总121. 买卖股票的最佳时机
    【云原生】Kubernetes----Metrics-Server组件与HPA资源
    计算机网络:数据链路层
    声明式HTTP客户端-Feign 使用入门详解
    git安装配置教程
    Python实现疫苗接种数据库管理——毕业设计经典案例
    Java基础知识
    计算机网络-计算机网络体系结构-物理层
  • 原文地址:https://blog.csdn.net/superatom01/article/details/139425330