前言
最近新入职的公司做的是LBS相关的项目,一般会对一些地理位置及相关数据做操作。一般存储每个地点的经纬度的坐标,组成点坐标或是多边形、矩形、圆形等区域,也可能是球面。会有一些应用场景,比如一辆车越过电子围栏区域触发报警,就比如查询一个点是否在指定区域内。或查询某个坐标点附近的地理位置场所坐标,而Mongodb专门针对这种查询建立了地理空间索引,主要分为2d和2dsphere两种分别是针对平面和球面。Mongo的位置信息查询性能非常高。
查询点是否在区域内
实体类,构建2dsphere类型的索引
@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;
}
数据访问,新增和查询点是否在数据库已存数据的某个区域内
@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;
}
}
测试用例,创建区域的时候,坐标数组的首末坐标一致。
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不存在存在该点的区域");
}
}
使用指令:
创建索引,插入区域对象
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],
]]
}
}
);
db.area.find(
{
geoJsonPolygon:
{
$geoIntersects:
{
$geometry:{
"type" : "Point",
"coordinates" : [113.330908,23.155678] }
}
}
}
);
结果如下图
点坐标换下查询结果如下图