地理空间索引
本教程共 50 篇 · 第 44 篇 · 更新于 2026-07-30 · 约 3 分钟阅读
44. 地理空间索引
本节目标:会存 GeoJSON 坐标、建 2dsphere 索引,并用 $near、$geoWithin、$geoIntersects 做空间查询。
很多业务要回答「离我最近的店」「这个区域内的商品」。MongoDB 用地理空间索引(Geospatial Index)支持这类查询。我们的 products 正好带了 location 字段。
44.1 GeoJSON:坐标怎么存
MongoDB 推荐用 GeoJSON 对象存地理数据。它就是一个内嵌文档,含 type 和 coordinates 两个字段。
// products 里每个商品带一个 Point 位置
test> db.products.insertMany([
{ _id: 11, name: "西湖店键盘", price: 399, category: "外设",
location: { type: "Point", coordinates: [120.15, 30.25] } },
{ _id: 12, name: "武林店鼠标", price: 89, category: "外设",
location: { type: "Point", coordinates: [120.16, 30.27] } },
{ _id: 13, name: "滨江店耳机", price: 199, category: "外设",
location: { type: "Point", coordinates: [120.21, 30.20] } }
])
WarningGeoJSON 坐标顺序是「经度在前,纬度在后」
[经度, 纬度]。写反了位置会跑到地球另一端,这个坑我见过不止一次。
常见 GeoJSON 类型有三种:
Point:点,比如一家门店。LineString:线,比如一条配送路线。Polygon:面,比如一个配送圈或行政区。
44.2 建 2dsphere 索引
球面计算要用 2dsphere 索引。它基于 WGS84 参考系,按地球曲面算距离。
// 给 location 建 2dsphere 索引
test> db.products.createIndex({ location: "2dsphere" })
Note平面计算用老的
2d索引;真实经纬度场景一律用2dsphere,别用错。
44.3 $near:找离我最近的
$near 按距离从近到远返回,且必须配合地理空间索引。
// 以西湖坐标为圆心,找 5 公里内的商品
test> db.products.find({
location: {
$near: {
$geometry: { type: "Point", coordinates: [120.15, 30.25] },
$maxDistance: 5000
}
}
})
不写 $maxDistance 也会返回,只是不限最远距离。结果与距离从小到大排列。
44.4 $geoWithin:圈出一个范围
$geoWithin 选出落在某形状内的文档,不会排序。常用 $centerSphere 画一个圆(单位是弧度):
// 以指定点为中心、半径 10 公里(约 0.00157 弧度)的圆内商品
test> db.products.find({
location: {
$geoWithin: {
$centerSphere: [ [120.15, 30.25], 10 / 6378.1 ]
}
}
})
也可以用 Polygon 圈一个任意多边形区域:
// 用多边形框选一片区域
test> db.products.find({
location: {
$geoWithin: {
$geometry: {
type: "Polygon",
coordinates: [ [ [120.10, 30.20], [120.25, 30.20], [120.25, 30.30], [120.10, 30.30], [120.10, 30.20] ] ]
}
}
}
})
44.5 $geoIntersects:判断相交
$geoIntersects 用来判断几何是否相交。比如一条配送路线(LineString)是否经过某个区域(Polygon)。
// 一条路线是否穿过上面的配送圈
test> db.routes.find({
path: {
$geoIntersects: {
$geometry: {
type: "Polygon",
coordinates: [ [ [120.10, 30.20], [120.25, 30.20], [120.25, 30.30], [120.10, 30.30], [120.10, 30.20] ] ]
}
}
}
})
Tip记住三个算子的分工:
$near管「最近排序」,$geoWithin管「圈内筛选」,$geoIntersects管「是否相交」。
44.6 小结
地理数据用 GeoJSON 存(经度在前)。建 2dsphere 索引后,用 $near 查最近、$geoWithin 圈范围、$geoIntersects 判相交。Point、LineString、Polygon 三类形状覆盖绝大多数位置场景。