您的位置:首页 > 数据库 > Mongodb

基于Springboot使用MongoDB进行简单Gis操作

2017-09-15 15:26 791 查看
  MongoDB使用json数据结构进行数据存储和组织,并提供了对gis的操作支持。mongoDB中基于GeoJson数据格式存储地理信息,并提供了一组函数对地理信息进行操作。因为项目需要,需要进行简单gis操作。在此就简单应用详述一二。

GeoJson数据格式

  GeoJson数据本质是一个json字符串,保存地理位置信息。

关于GeoJson数据的详细形式,及说明可参见官网

下面列举项目中一个简单的geojson字符串,描述的是一个地理区域。

{
"_id" : 1,
"regionName" : "北京市",
"regionCode" : "010",
"regionType" : "province"
"geometry" : {
"type" : "Polygon", //geojson中地理类型,在此表示一个区域类型,其他类型可参考geojson官方文档。
"coordinates" : [ //用于描述地理详细信息,一个[x,y]表示一个点的坐标[经度,纬度],在此区域信息,可以是一个包含多个点的闭环区域,首末坐标相同,形成闭环。
[
[
117.209782,
40.082243
],
[
117.116937,
40.071038
],
... ,
[
117.209782,
40.082243
]
]
]
}
}


  描述一个点的geojson字符串。

{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Point",
"coordinates": [
110.654296875,
41.902277040963696
]
}
}
]
}


  可以在geojson.io得到在线生成的geojson数据。

基于Springboot的mongodb gis操作

  下面介绍一个地理围栏功能的功能实现,以此论述mongoDB对gis的操作过程。地理围栏功能,即给定一个点坐标,判断是否在一个指定区域内,超出就报警。

  新建Springboot项目,添加mongoDB的相关依赖jar包,并配置好数据库连接,使用mongo中数据库为gis,具体方式参见之前的文章。新建Collection,名称为geographicalRegion,保存地理信息对象。示例如下:

{
"_id" : 1,
"regionName" : "北京市",
"regionCode" : "010",
"regionType" : "province",
"geometry" : {
"type" : "Polygon",
"coordinates" : [...]
}
}


创建geoJson的domain对象。Spring-data-mongodb提供了对geoJson的抽象封装。提供了GeoJsonPolygon、Polygon、Line、GeoJsonPoint等类对geojson相关属性进行封装。

我们定义GisRegion对象,用来保存geojson地理信息,以及相关区域的名称和标识码code。如下所示:

@Document(collection = "geographicalRegion")  //spring.data为mongodb定义的注解,直接映射数据库的document名称
public class GisRegion {

@Id  //指定字段的主键字段
private int locationId;

@Field("regionName")  //属性映射数据库document属性名称,若未指定,默认存储实体类属性名称
private String regionName;
private String regionCode;
private String regionType;
private GeoJsonPolygon geometry;

public int getLocationId() {
return locationId;
}

public void setLocationId(int locationId) {
this.locationId = locationId;
}

public String getRegionName() {
return regionName;
}

public void setRegionName(String regionName) {
this.regionName = regionName;
}

public String getRegionCode() {
return regionCode;
}

public void setRegionCode(String regionCode) {
this.regionCode = regionCode;
}

public String getRegionType() {
return regionType;
}

public void setRegionType(String regionType) {
this.regionType = regionType;
}

public GeoJsonPolygon getGeometry() {
return geometry;
}

public void setGeometry(GeoJsonPolygon geometry) {
this.geometry = geometry;
}
}


  自定义数据库dao并使用MongoTemplate。

@Component
public class GeoJsonDaoImpl {
@Autowired
private MongoTemplate mongoTemplate;

public void savePolygon(Polygon polygon){
mongoTemplate.save(polygon);
}

public void saveRegions(List<GisRegion> gisRegionList){
mongoTemplate.insert(gisRegionList,GisRegion.class);
}

//使用mongoTemplate封装的intersects方法判断输入geojson信息是否在数据库保存的地理区域内。并返回相关区域信息列表
public List<Polygon> findIntersective(GeoJson geoJson){
Query query=new Query(Criteria.where("geometry").intersects(geoJson));
List<Polygon> list=mongoTemplate.find(query,Polygon.class);
return list;
}
//查找目标区域是否在指定的几个区域内,locations的set中保存指定的区域id
//有时数据库中保存的geojson地理信息数据集比较大,整个对象返回往往会消耗很大的io和带宽,所以我们在这里指定仅返回区域的_id,并且只要判断目标geojson是指定的一个区域的子集就返回结果,降低数据库的处理开销
public boolean isInRegion(GeoJsonPoint point,Set locations){
Criteria geoCriteria=Criteria.where("geometry").intersects(point);

Criteria[] orArr=new Criteria[locations.size()];
Iterator<Integer> iterator=locations.iterator();
int i=0;
while(iterator.hasNext()){
orArr[i]=new Criteria("_id").is(iterator.next());
i++;
}
Criteria orCriteria=new Criteria().orOperator(orArr);
Criteria andCriteria=new Criteria().andOperator(geoCriteria,orCriteria);

DBObject field=new BasicDBObject();
field.put("_id",true);

Query query=new BasicQuery(new BasicDBObject(),field);
query.addCriteria(andCriteria);

GeographicalRegion region=mongoTemplate.findOne(query, GeographicalRegion.class);
if(region==null){
return false;
}
return true;
}
}


测试方法:

public void findIntersectiveTest() throws IOException {
GeoJsonDaoImpl geoJsonDaoImpl=new GeoJsonDaoImpl();
GeoJson geoJson=new GeoJsonPoint(1,1);
System.out.println(geoJsonDaoImpl.findIntersective(geoJson));
Set<Integer> locationIds=new HashSet<Integer>();
locationIds.add(1);
locationIds.add(2);
System.out.println(mongoDao.isInRegion(point, locationIds));
}


关于mongoDB中对地理位置的其他操作,例如搜索指定范围内的指定目标,目标点附近的指定目标等功能都有支持,spring-data-mongodb中都提供了封装函数。可以在MongoTemplate中查看更多的gis操作方法。基于MongoDB更复杂的gis交互,有待进一步研究。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: