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
        }
    }
]);
相关推荐
Bruce-li__2 小时前
DRF凭什么更高效?Django原生API与DRF框架开发对比解析
数据库·django·sqlite
18538162800余--2 小时前
矩阵系统私信功能开发技术实践,支持OEM
线性代数·矩阵
noravinsc2 小时前
connection.cursor() 与 models.objects.filter
数据库·django·原生查询·orm查询
laimaxgg4 小时前
MySQL复合查询
数据库·mysql
编程在手天下我有4 小时前
Redis 常见问题深度剖析与全方位解决方案指南
数据库·redis·缓存·性能优化·数据持久化·分布式系统
辰哥单片机设计5 小时前
JQ6500语音模块详解(STM32)
数据库·mongodb
阿桨6 小时前
【保姆级教程-Centos7环境下部署mongodb并设置开机自启】
数据库·mongodb·centos
18538162800余--6 小时前
短视频矩阵系统可视化剪辑功能开发,支持OEM
线性代数·矩阵·音视频
lolo大魔王6 小时前
MongoDB的增删改查操作
数据库·mongodb
layman05287 小时前
node.js 实战——mongoDB
数据库·mongodb·node.js