必须确保数据为合法geojson格式(type="point"、coordinates=[经度,纬度])、创建2dsphere索引、使用$geowithin配合闭合polygon坐标或$box矩形查询,三者缺一不可。

要在MongoDB中快速查出落在指定多边形区域内的所有地点,必须确保数据格式合规、索引类型匹配、查询语法精确,三者缺一不可。
确认数据存储为合法GeoJSON格式
检查集合中文档的地理字段是否严格符合GeoJSON规范:type字段值必须为字符串"Point"(首字母大写),coordinates必须是长度为2的数组,且【顺序必须是[经度, 纬度]】——若颠倒为[纬度, 经度],$geoWithin将始终返回空结果,且不报错。
运行db.places.findOne()观察loc字段结构,正确示例:{"type": "Point", "coordinates": [-73.97, 40.77]};错误示例:{"type": "point", "coordinates": [40.77, -73.97]}(小写type + 坐标颠倒)。
若发现不一致,需用updateMany批量修正,例如:db.places.updateMany({ "loc.type": "point" }, [ { $set: { "loc.type": { $literal: "Point" } } } ])。
创建2dsphere索引
执行命令:db.places.createIndex({ "loc": "2dsphere" })。
这一步不可跳过——虽然$geoWithin本身不要求索引也能运行,但【没有2dsphere索引时,多边形查询会退化为全表扫描】,万级文档以上响应时间从毫秒级飙升至数秒甚至超时。
索引创建完成后,可用db.places.getIndexes()验证是否存在{"loc": "2dsphere"}条目。
编写正确的$geoWithin多边形查询
方法一:手写闭合多边形坐标数组
第一步:确定四个顶点经纬度,例如北京五环内矩形区域:西北角(-116.45, 40.05)、东北角(-116.40, 40.05)、东南角(-116.40, 39.85)、西南角(-116.45, 39.85);
第二步:按顺时针或逆时针顺序排列坐标,并复制第一个点到末尾完成闭合;
第三步:构造查询语句:db.places.find({ loc: { $geoWithin: { $geometry: { type: "Polygon", coordinates: [[[-116.45,40.05],[-116.40,40.05],[-116.40,39.85],[-116.45,39.85],[-116.45,40.05]]] } } } })。
方法二:用$box简化矩形查询(仅限矩形)
若多边形恰好是轴对齐矩形,改用更轻量的$box:db.places.find({ loc: { $geoWithin: { $box: [[-116.45,39.85], [-116.40,40.05]] } } })。注意$box内部两个点分别是西南角和东北角,无需闭合。
方法三:从外部GeoJSON文件导入复杂多边形
将标准GeoJSON Polygon对象(含type和coordinates字段)存为变量polygonGeo,再代入查询:db.places.find({ loc: { $geoWithin: { $geometry: polygonGeo } } })。此法适合行政区划等上百顶点的不规则形状。











