前言
如果是LBS相关的项目,一般会对一些地理位置及相关数据做操作。一般存储每个地点的经纬度的坐标,组成点坐标或是多边形、矩形、圆形等区域,也可能是球面。
这边会涉及一些应用场景,比如一辆车越过电子围栏区域触发报警,就比如查询一个点是否在指定区域内。或查询某个坐标点附近的地理位置场所坐标,而Mongodb专门针对这种查询建立了地理空间索引,主要分为2d和2dsphere两种分别是针对平面和球面。Mongo的位置信息查询性能非常高。
查询点是否在区域内
1 2 |
实体类,构建2dsphere类型的索引 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
@Data @Document(collection = "area") @CompoundIndexes({ @CompoundIndex(name = "2dsphere_index_01", def = "{'geoJsonPolygon': '2dsphere'}"), }) public class Area { @Id private String id; private String name; //区域点坐标集合 多边形 private GeoJsonPolygon geoJsonPolygon; } |
1 2 |
数据访问,新增和查询点是否在数据库已存数据的某个区域内 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
@Repository public class AreaRepository { @Autowired private MongoTemplate mongoTemplate; public void insert(Area area){ mongoTemplate.insert(area); } public boolean pointIsInArea(GeoJsonPoint point){ Query query = new Query(); query.addCriteria(Criteria.where("geoJsonPolygon").intersects(point)); Area area = mongoTemplate.findOne(query,Area.class); return area != null; } } |
1 2 |
测试用例,创建区域的时候,坐标数组的首末坐标一致。 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
public class AreaTests extends MongoExploreApplicationTests { @Autowired private AreaRepository areaRepository; @Test public void insert(){ Area area = new Area(); area.setName("一个测试的多边形区域"); area.setGeoJsonPolygon( new GeoJsonPolygon( new Point(113.314882,23.163055), new Point(113.355845,23.167042), new Point(113.370289,23.149564), new Point(113.356779,23.129758), new Point(113.338238,23.13913), new Point(113.330979,23.124706), new Point(113.313588,23.140858), new Point(113.323865,23.158204), new Point(113.314882,23.163055) ) ); areaRepository.insert(area); } @Test public void pointIsInArea(){ GeoJsonPoint geoJsonPoint = new GeoJsonPoint(113.330908,23.155678); boolean exist = areaRepository.pointIsInArea(geoJsonPoint); Assert.isTrue(exist,"DB不存在存在该点的区域"); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
使用指令: 创建索引,插入区域对象 db.area.ensureIndex( { geoJsonPolygon: "2dsphere" } ); db.area.insert( { geoJsonPolygon: { type:"Polygon", coordinates:[[ [113.314882,23.163055], [113.355845,23.167042], [113.370289,23.149564], [113.356779,23.129758], [113.338238,23.13913], [113.330979,23.124706], [113.313588,23.140858], [113.323865,23.158204], [113.314882,23.163055], ]] } } ); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
db.area.find( { geoJsonPolygon: { $geoIntersects: { $geometry:{ "type" : "Point", "coordinates" : [113.330908,23.155678] } } } } ); |
1 2 |
结果如下图 |
1 2 |
点坐标换下查询结果如下图 |
0