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
        }
    }
]);
相关推荐
WineMonk34 分钟前
Neo4j 图数据库 高级操作
数据库·neo4j
yogima42 分钟前
在Spring Data JPA中使用@Query注解
java·数据库·spring
醇氧1 小时前
【MySQL】哪些平台支持MySQL 数据库
数据库·mysql
shai.1 小时前
sql约束
数据库
wang_book1 小时前
redis学习(003 数据结构和通用命令)
java·数据库·redis·学习
结衣结衣.2 小时前
完全理解C语言函数
java·linux·c语言·数据库·经验分享·笔记
ItKevin爱java2 小时前
JDBC中如何处理数据库连接超时和SQL超时?
数据库·sql
2401_857622662 小时前
【SQL Server高可用性全解】构建永不宕机的数据库解决方案
数据库·oracle
youhebuke2252 小时前
SQLAlchemy pool_pre_ping
数据库·oracle·sqlalchemy
白菜!!!2 小时前
SQL INSERT批量插入方式
数据库·sql·mysql·mybatis