MongoDB 地理空间查询
本章介绍以下几点:
- 地理空间数据
- 地理空间索引
- 地理空间查询
- 地理空间模型
- 例子
MongoDB支持对地理空间数据的查询操作。本节介绍MongoDB的地理空间特性。
1.地理空间数据
在MongoDB中,可以将地理空间数据存储为GeoJSON对象或遗留坐标对。
1.1 GeoJSON对象
要计算类地球体上的几何形状,请将位置数据存储为GeoJSON对象。
要指定GeoJSON数据,请使用带有以下内容的嵌入式文档:
- 指定GeoJSON对象类型的名为type的字段和
- 指定对象坐标的名为coordinates的字段。
如果指定经纬度坐标,首先列出经度,然后是纬度:
- 有效经度值在-180和180之间,两者都包括在内。
- 有效纬度值在-90和90之间,两者都包括在内。
<field>: { type: <GeoJSON type> , coordinates: <coordinates> }
例如,要指定一个GeoJSON点:
location: {type: "Point",coordinates: [-73.856077, 40.848447]
}
有关MongoDB中支持的GeoJSON对象的列表和示例,请参见GeoJSON对象。
MongoDB在一个球体上计算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> }
要指定遗留坐标对,首选数组而不是嵌入式文档,因为某些语言不保证关联映射顺序。
空间索引
MongoDB提供了以下地理空间索引类型来支持地理空间查询。
2dsphere
2dsphere索引支持在类地球体上计算几何图形的查询。
要创建一个2dsphere索引,使用db.collection.createIndex()方法并指定字符串文字“2dsphere”作为索引类型:
db.collection.createIndex( { <location field> : "2dsphere" } )
其中,<location字段>的值是一个GeoJSON对象或一个遗留坐标对。
有关2dsphere索引的更多信息,请参见2dsphere索引。
2d
2d索引支持在二维平面上计算几何图形的查询。虽然该索引可以支持在一个球体上计算的$nearSphere查询,但是如果可能的话,可以对球形查询使用2dsphere索引。
要创建2d索引,使用db.collection.createIndex()方法,指定location字段作为键,字符串文字“2d”作为索引类型:
db.collection.createIndex( { <location field> : "2d" } )
其中,<location字段>的值是一个遗留坐标对。
有关2d索引的更多信息,请参见2d索引。
地理空间索引和切分集合
在对集合进行分片时,不能使用地理空间索引作为分片键。但是,可以使用不同的字段作为切分键,在切分集合上创建地理空间索引。
分片集合支持以下地理空间操作:
- $geoNear聚合阶段
- $near和$near sphere查询操作符(从MongoDB 4.0开始)
从MongoDB 4.0开始,$near和$near sphere查询支持切分集合。
在早期的MongoDB版本中,$near和$near sphere查询不支持切分集合;相反,对于分片集群,必须使用$geoNear聚合阶段或geoNear命令(在MongoDB 4.0和更早的版本中可用)。
您还可以使用$geoWithin和$geoIntersect来查询切分集群的地理空间数据。
覆盖查询
地理空间索引无法覆盖查询。
地理空间查询
提示:
对于球形查询,使用2dsphere索引结果。
对球形查询使用2d索引可能会导致不正确的结果,例如对围绕极点的球形查询使用2d索引。
地理空间查询操作符
MongoDB提供了以下地理空间查询操作:
Name | Description |
---|---|
$geoIntersects
|
选择与GeoJSON几何图形相交的几何图形。2dsphere索引支持$geoIntersects。 |
$geoWithin
|
选择包围GeoJSON几何图形中的几何图形。2dsphere和2d索引支持$geoWithin。 |
$near
|
返回一个点附近的地理空间对象。需要地理空间索引。2dsphere和2d索引支持$near。 |
$nearSphere
|
返回接近球体上某一点的地理空间对象。需要地理空间索引。2dsphere和2d索引支持$nearSphere。 |
有关详细信息(包括示例),请参见各个参考页面。
地理空间聚合阶段
MongoDB提供了以下地理空间聚集管道阶段:
Stage | Description |
---|---|
$geoNear
|
根据与地理空间点的接近程度返回有序的文档流。为地理空间数据合并了$match、$sort和$limit功能。输出文档包含一个额外的距离字段,并且可以包含一个位置标识符字段。 |
有关更多细节,包括示例,请参见$geoNear参考页面。
地理空间模型
MongoDB地理空间查询可以解释平面或球体上的几何图形。
2dsphere索引只支持球形查询(即在球形表面上解释几何图形的查询)。
2d索引支持平面查询(即在平面上解释几何图形的查询)和一些球形查询。虽然2d索引支持一些球形查询,但是对这些球形查询使用2d索引可能会导致错误。如果可能,对球形查询使用2dsphere索引。
下表列出了地理空间查询操作符,支持查询,每个地理空间操作使用:
Operation | Spherical/Flat Query | Notes |
---|---|---|
$near (GeoJSON centroid point in this line and the following line, 2dsphere index)
|
Spherical | 还请参阅$nearSphere操作符,它在与GeoJSON和2dsphere索引一起使用时提供了相同的功能。 |
$near (legacy coordinates, 2d index)
|
Flat | |
$nearSphere (GeoJSON point, 2dsphere index)
|
Spherical |
提供与使用GeoJSON点和a2dsphere索引的$near操作相同的功能。 对于球形查询,最好使用$nearSphere,它在名称中显式地指定球形查询,而不是$near操作符。 |
$nearSphere (legacy coordinates, 2d index)
|
Spherical | Use GeoJSON points instead. |
$geoWithin : { $geometry : … }
|
Spherical | |
$geoWithin : { $box : … }
|
Flat | |
$geoWithin : { $polygon : … }
|
Flat | |
$geoWithin : { $center : … }
|
Flat | |
$geoWithin : { $centerSphere : … }
|
Spherical | |
$geoIntersects
|
Spherical | |
$geoNear aggregation stage (2dsphere index)
|
Spherical | |
$geoNear aggregation stage (2d index)
|
Flat |
例子
使用以下文件创建集合地点:
db.places.insert( {name: "Central Park",location: { type: "Point", coordinates: [ -73.97, 40.77 ] },category: "Parks"
} );
db.places.insert( {name: "Sara D. Roosevelt Park",location: { type: "Point", coordinates: [ -73.9928, 40.7193 ] },category: "Parks"
} );
db.places.insert( {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"}}
] )
二、查找具有地理空间查询的餐馆
概述
MongoDB的地理空间索引允许您高效地对包含地理空间形状和点的集合执行空间查询。为了展示地理空间特性的功能并比较不同的方法,本教程将指导您编写一个简单的地理空间应用程序的查询过程。
本教程将简要介绍地理空间索引的概念,然后演示它们在$geoWithin、$geoIntersects和$nearSphere中的用法。
假设您正在设计一个移动应用程序来帮助用户查找纽约市的餐馆。应用程序必须:
- 使用$geoIntersects来确定用户当前的邻域,
- 使用$geoWithin显示该社区的餐馆数量,以及
- 使用$nearSphere查找用户指定距离内的餐馆。
本教程将使用一个2dsphere索引来查询关于球面几何的数据。
有关球面和平面几何的更多信息,请参见地理空间模型。
失真
由于将三维球体(如地球)投射到平面上的特性,当在地图上显示时,球面几何将会扭曲。
例如,以经纬度点(0,0)、(80,0)、(80,80)和(0,80)定义的球面平方为例。下图描绘了该区域所覆盖的区域:
寻找餐馆
前提条件
从https://raw.githubusercontent.com/mongodb/docs-assets/geospatial/neighborhoods.json和https://raw.githubusercontent.com/mongodb/docs-assets/geospatial/restaurants.json下载示例数据集。这些分别包含收集餐馆和社区。
下载数据集后,导入数据库:
mongoimport <path to restaurants.json> -c=restaurants
mongoimport <path to neighborhoods.json> -c=neighborhoods
一个地理空间索引,并且几乎总是提高$geoWithin和$geoIntersects查询的性能。
因为这些数据是地理上的,所以使用mongo shell在每个集合上创建一个2dsphere索引:
db.restaurants.createIndex({ location: "2dsphere" })
db.neighborhoods.createIndex({ geometry: "2dsphere" })
探索数据
从mongo外壳中查看新创建的餐馆集合中的一个条目:
db.restaurants.findOne()
该查询返回的文档如下:
{location: {type: "Point",coordinates: [-73.856077, 40.848447]},name: "Morris Park Bake Shop"
}
本餐厅文件对应的位置如下图所示:
因为本教程使用2dsphere索引,所以location字段中的几何数据必须遵循GeoJSON格式。
现在检查一个条目在邻里收集:
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纬度。为了找到当前的邻域,您将使用特殊的$geometry字段在GeoJSON格式中指定一个点:
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"
}
找到附近所有的餐馆
您还可以查询某个给定社区中包含的所有餐馆。在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以未排序的顺序返回结果,或者使用$maxDistance(如果需要按距离排序结果)来返回结果。
Unsorted with $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 } } })
GeoJSON对象
概述
MongoDB支持本页列出的GeoJSON对象类型。
要指定GeoJSON数据,请使用带有以下内容的嵌入式文档:
- 指定GeoJSON对象类型和的名为type的字段
- 指定对象坐标的名为coordinates的字段。
如果指定经纬度坐标,首先列出经度,然后是纬度:
- 有效经度值在-180和180之间,两者都包括在内。
- 有效纬度值在-90和90之间,两者都包括在内。
<field>: { type: <GeoJSON type> , coordinates: <coordinates> }
MongoDB在一个球体上计算GeoJSON对象的地理空间查询;MongoDB使用WGS84参考系统对GeoJSON对象进行地理空间查询。
点
下面的例子指定了一个GeoJSON点:
{ type: "Point", coordinates: [ 40, 5 ] }
LineString
下面的示例指定了一个GeoJSON LineString:
{ type: "LineString", coordinates: [ [ 40, 5 ], [ 41, 6 ] ] }
多边形
多边形由一组GeoJSON线性坐标数组组成。这些线性环是闭合的线性弦。闭合的线字符串至少有四个坐标对,并指定与第一个和最后一个坐标相同的位置。
连接两个点在曲面上的直线可能包含也可能不包含连接两个点在平面上的同一组坐标。在曲面上连接两个点的直线是测地线。仔细检查点,以避免错误与共享的边缘,以及重叠和其他类型的交叉。
只有一个环的多边形
下面的例子指定了一个GeoJSON多边形,它有一个外部环,没有内部环(或孔)。为了关闭多边形,第一个和最后一个坐标必须匹配:
{type: "Polygon",coordinates: [ [ [ 0 , 0 ] , [ 3 , 6 ] , [ 6 , 1 ] , [ 0 , 0 ] ] ]
}
对于单环多边形,环不能自交。
有多个环的多边形
对于多环多边形:
- 第一个描述的环必须是外环。
- 外环不能自交。
- 任何内圈都必须完全包含在外圈内。
- 内环不能相互交叉或重叠。内环不能共用一条边。
下面的例子表示一个带有内环的GeoJSON多边形:
{type : "Polygon",coordinates : [[ [ 0 , 0 ] , [ 3 , 6 ] , [ 6 , 1 ] , [ 0 , 0 ] ],[ [ 2 , 2 ] , [ 3 , 3 ] , [ 4 , 2 ] , [ 2 , 2 ] ]]
}
多点
需要的版本
GeoJSON多点嵌入式文档编码一个点列表。
{type: "MultiPoint",coordinates: [[ -73.9580, 40.8003 ],[ -73.9498, 40.7968 ],[ -73.9737, 40.7648 ],[ -73.9814, 40.7681 ]]
}
MultiLineString
需要的版本
下面的例子指定了一个GeoJSON MultiLineString:
{type: "MultiLineString",coordinates: [[ [ -73.96943, 40.78519 ], [ -73.96082, 40.78095 ] ],[ [ -73.96415, 40.79229 ], [ -73.95544, 40.78854 ] ],[ [ -73.97162, 40.78205 ], [ -73.96374, 40.77715 ] ],[ [ -73.97880, 40.77247 ], [ -73.97036, 40.76811 ] ]]
}
多个多边形
需要的版本
下面的例子指定了一个GeoJSON多多边形:
{type: "MultiPolygon",coordinates: [[ [ [ -73.958, 40.8003 ], [ -73.9498, 40.7968 ], [ -73.9737, 40.7648 ], [ -73.9814, 40.7681 ], [ -73.958, 40.8003 ] ] ],[ [ [ -73.958, 40.8003 ], [ -73.9498, 40.7968 ], [ -73.9737, 40.7648 ], [ -73.958, 40.8003 ] ] ]]
}
GeometryCollection
需要的版本
下面的例子存储了GeoJSON类型的GeometryCollection坐标:
{type: "GeometryCollection",geometries: [{type: "MultiPoint",coordinates: [[ -73.9580, 40.8003 ],[ -73.9498, 40.7968 ],[ -73.9737, 40.7648 ],[ -73.9814, 40.7681 ]]},{type: "MultiLineString",coordinates: [[ [ -73.96943, 40.78519 ], [ -73.96082, 40.78095 ] ],[ [ -73.96415, 40.79229 ], [ -73.95544, 40.78854 ] ],[ [ -73.97162, 40.78205 ], [ -73.96374, 40.77715 ] ],[ [ -73.97880, 40.77247 ], [ -73.97036, 40.76811 ] ]]}]
}
MongoDB 地理空间查询相关推荐
- MongoDB地理空间移动演示
蒙古语:名词(pl mongo或mongos)–蒙古的货币单位. 等于图格里克的百分之一. 源自蒙古语"银" 我已经写过有关NoSQL DBMS的文章[ http://keyhol ...
- ES GEO地理空间查询java版
ES GEO地理空间查询java版 一.半径范围查询 1.设置mapping,类型为geo_point PUT /my_locations {"mappings": {" ...
- mongodb 地理距离_MongoDB地理空间移动演示
mongodb 地理距离 蒙古语:名词(pl mongo或mongos)–蒙古的货币单位. 等于图格里克的百分之一. 源自蒙古的"银" 我已经写过有关NoSQL DBMS的文章[ ...
- Elasticsearch地理空间之geo_shape
参考文章: Elasticsearch地理形状 Elasticsearch geo_shape地理形状 ES地理范围查询第二讲:地理位置信息之geo_shape ES GEO地理空间查询java版 E ...
- mongodb空间查询之查询单位
1.建立空间索引 db.collection.ensureIndex({'geom.coordinates':'2d'}) 2.空间查询 这里遇到的问题是查询的时候会涉及到范围,那么这个范围的单位是什 ...
- mongodb高级聚合查询
在工作中会经常遇到一些mongodb的聚合操作,特此总结下.mongo存储的可以是复杂类型,比如数组.对象等mysql不善于处理的文档型结构,并且聚合的操作也比mysql复杂很多. 注:本文基于 mo ...
- 详解基于MongoDB的地理位置查询,结合Symfony2演示
简介 随着近几年各类移动终端的迅速普及,基于地理位置的服务(LBS)和相关应用也越来越多,而支撑这些应用的最基础技术之一,就是基于地理位置信息的处理.我所在的项目也正从事相关系统的开发,我们使用的是S ...
- MongoDB 进阶-关联查询
[苏州需要工作的加我QQ,内推介绍费平分] MongoDB 进阶 1.数据库命令 a.命令的工作原理 drop命令,在shell中删除一个集合,执行db.refactor.drop().其实这个函数实 ...
- asp 取数据 计算_地学数据 | 地理空间数据获取方式汇总
1.测绘地理信息局会 (http://www.webmap.cn/main.do?method=index) 该网站提供:30米全球地表覆盖数据,GlobeLand30能够提供包括:地理位置.分布范围 ...
最新文章
- java 数字三角形_数字三角形 Number Triangles(java的MLE解决办法)
- Docker容器中MySQL最大连接数被限制为214的解决方案
- Docker 入门(Mac环境)- part 5 stacks
- SAP Cloud for Customer最新版本2002 RUI如何启用adaptation模式
- 媒体格式分析之flv -- 基于FFMPEG
- C++ 高级篇(五)—— 预处理指令
- 【剑指offer】面试题56 - II:数组中数字出现的次数 II(Java)
- 安装配置ASMlib驱动
- python3 音乐播放器_Python3——MP3播放器
- 爆料称华为P50系列即将进入量产 或将于下月发布
- JSK-115 单独的数字(二)【位运算】
- 【leetcode】面试题 03.03. 堆盘子vector_stack的使用
- css vue 内联_vue ssr css内联样式和link标签重复
- 日处理数据量超10亿:友信金服基于Flink构建实时用户画像系统的实践
- JS设计模式-单例模式
- 将m个相同的球全部放到n个相同的盒子里面有几种放法,盒子不能为空
- JAVA-----集合子接口Queue及其子接口Deque
- 关于trycatchfinal返回值问题
- 【力扣】714. 买卖股票的最好时机含手续费
- csv 文件读写乱码问题的一个简单解决方法
热门文章
- 如何使用iMacros自动化重复的网页浏览器任务
- 使用小程序制作一个电子木鱼,功德+1
- 【附源码】计算机毕业设计java智能仓储设备管理系统设计与实现
- 2021-07-09 支付行业发展特点与所面临的挑战需求
- Linux服务器 大量的CLOSE_WAIT、TIME_WAIT解决办法
- 概述笔记 TREC 2020|OVERVIEW OF THE TREC 2020 DEEP LEARNING TRACK
- 未曾清贫难成人,不经打击老天真。
- linux alsa驱动讲解
- 职业“小三劝退师”,真的能拯救你的婚姻吗?
- Datadog 笔记