Mongodb地理信息数据查询

学习mongodb,体会mongodb的每一个使用细节,欢迎阅读威赞的文章。这是威赞发布的第78篇mongodb技术文章,欢迎浏览本专栏威赞发布的其他文章。如果您认为我的文章对您有帮助或者解决您的问题,欢迎在文章下面点个赞,或者关注威赞。谢谢。

通过阅读文档,了解Mongodb除了支持文档查询外,还支持地理信息坐标及临近查询。本文就对Mongodb对地理信息查询的支持进行介绍。

地理信息数据

在Mongodb数据库中,用户可以使用GeoJSON对象或者经纬坐标对的形式来保存地理信息数据。

GeoJSON对象

Mongodb使用GeoJSON对象保存数据以便于在地理空间中进行计算。用户使用嵌入文档的形式定义GeoJSON对象的数据,包括

  • 一个名为type的字段,定义了GeoJSON对象的类型

  • 一个名为coordinates的字段,指定了对象的坐标信息

    <field>: { type: <GeoJSON type>, coordinates: <coordinates>}

如定义一个GeoJSON类型的点

复制代码
location:  {
    type: "Point",
    coordinates: [-73.856077, 40.848447]
}

当然,Mongodb也支持定义GeoJSON列表,具体可以参考本系列的其他文章。

Mongodb计算地理信息数据时,使用WGS84坐标系。

经纬坐标对

为了计算欧式距离,除了定义GeoJSON对象外,用户还可以将数据保存为经纬坐标对的形式,并建立一个平面二维索引。当用户将经纬坐标对转换成GeoJSON点类型的数据后,利用空间二维索引,Mongodb可以支持曲面空间数据计算。

用户可以使用数组或嵌入文档的形式,来保存坐标对数据。mongodb推荐用户使用数组的形式来保存数据。

复制代码
<field>: [<x>, <y>]

或者使用经纬度坐标

复制代码
<field>:[<经度坐标>, <纬度坐标>]

其中经度坐标范围在-180到180之间,包含-180和180. 而纬度坐标是-90到90之间,同样包含-90和90.

使用嵌入式文档的形式来定义坐标对

复制代码
<field>: {<field1>: <x>, <field2>: <y>}

或者使用经纬度坐标来定义位置信息。

复制代码
<field>: { <field1>: <longitude>, <field2>: <latitude>}

与使用数组定义一致,经度定义在-180到180之间,包含-180和180两个数值。纬度在-90到90之间,同样包含两个边界。

地理信息索引

为了提高地理信息查询的性能,mongodb允许用户添加地理信息索引来时间数据的快速查询和计算。

二维空间索引

二维空间索引,支持曲面地理信息计算

用户使用db.collection.createIndex建立二维空间索引. 其中<location field>可以是一个坐标对或者GeoJSON类型的对象。

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

二维平面索引

二维平面支持在两个维度的平面地理信息查询。尽管二维平面索引支持使用$nearSphere的空间查询,但用户在进行空间地理信息查询时,尽量使用二维空间索引。

用户使用db.collection.createIndex()方法,来创建二维平面索引。

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

其中,<location field>字段是坐标对。

地理信息查询

用户使用二维平面索引查询时,mongdb可能会返回错误的数据或者报错。例如二维平面索引不支持跨越极点的查询 。

地理信息查询操作符

mongodb提供了4个操作符 ,用于查询地理信息。

|----------------|-------------|
| 操作符 | 描述 |
| geoIntersects | 查询相交的地理信息数据 | | geoWithin | 查询包含的地理信息数据 |
| near | 查询临近的平面地理对象 | | nearSphere | 查询临近的空间地理对象 |

聚合管道中的地理信息操作符

mongodb同样提供了一个应用在聚合管道中的地理信息操作符

|----------|--------------------------------------------------------------|
| 操作符 | 描述 |
| geoNear | 查询临近指定点的空间数据文档, 与match, sort, limit配合使用。输出文档包含了一个额外的距离字段。 |

地理信息模型

mongodb的地理信息查询可以在平面坐标系当中执行,也可以应用在空间查询当中。

使用二维空间索引时,只能进行空间当中的地理信息查询。而使用二维平面索引时,既可以进行平面空间查询,也可以进行部分空间查询。用户使用二维平面索引查询时,mongdb可能会返回错误的数据或者报错。下面的表格,列出了空间查询操作符所支持的查询空间类型和备注信息。

|------------------------------------|----------|
| 操作符 | 支持查询空间类型 |
| near(使用GeoJSON对象进行查询,集合中包含2d空间索引) | 空间 | | near(使用坐标对象进行查询,集合中包含2d平面索引) | 平面 |
| nearSphere(GeoJSON点,二维空间索引) | 空间 | | nearSphere(坐标点,二维平面索引) | 空间 |
| geoWithin: {geometry:...} | 空间 |
| geoWithin: {box:...} | 平面 |
| geoWithin: {polygon:...} | 平面 |
| geoWithin: {center:...} | 平面 |
| geoWithin: {centerSphere:...} | 空间 |
| geoIntersects | 空间 | | 聚合管道中的geoNear, 带有二维空间索引 | 空间 |
| 聚合管道中的$geoNear, 带有二维平面索引 | 平面 |

应用

创建集合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.8308] },
        category: "Stadiums"
    }
]);

创建二维空间索引

复制代码
db.places.createIndex({ location: "2dsphere" });

编写查询语句,要求查询出距离点{ type: "Point", coordinates: [-73.9667, 40.78]一公里到五公里范围内的兴趣点。

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

构建管道查询,查询出点{ type: "Point", coordinates: [ -73.9667, 40.78 ] }附近的公园信息

复制代码
db.places.aggregate([
    {
        $geoNear: {
            near: { type: "Point", coordinates: [-73.9667, 40.78] },
            distanceField: "calcDistance",
            query: { category: "Parks" },
            spherical: true
        }
    }
]);
相关推荐
田梓燊32 分钟前
定积分的应用(4.39-4.48)
线性代数·概率论
死磕java的孤行者40 分钟前
Redis 分布式锁
数据库·redis·分布式
越甲八千42 分钟前
pyqt SQL Server 数据库查询-优化2
数据库·windows·pyqt
lisw051 小时前
编程范式演进与开发者能力矩阵重构
线性代数·矩阵·重构
敢敢のwings1 小时前
C++信号与槽机制自实现
开发语言·数据库·c++
杭州杭州杭州2 小时前
MySQL超全笔记
数据库·笔记·mysql
OpenVINO生态社区4 小时前
【汽车功能安全:软件与硬件缺一不可】
数据库·安全·汽车
程序猿阿伟5 小时前
《打破SQL与AI框架对接壁垒,解锁融合新路径》
数据库·人工智能·sql
点燃大海6 小时前
MySQL表结构导出(Excel)
java·数据库·python·mysql·spring
꧁坚持很酷꧂6 小时前
Qt远程连接数据库,注册,登录
开发语言·数据库·qt