嘉兴市住房和城乡建设局网站,巩义网站建设方案报价,厦门做网站维护的公司,连云港专业做网站一、概念说明
1.1 空间地理数据 MongoDB 中使用 GeoJSON对象 或 坐标对 描述空间地理数据。MongoDB使用 WGS84 参考系进行地理空间数据查询。 1、MongoDB支持空间数据的存储#xff0c;数据类型需要限制为GeoJSON; 2、MongoDB可以为GeoJSON类型数据建立索引#xff0c;提升空…一、概念说明
1.1 空间地理数据 MongoDB 中使用 GeoJSON对象 或 坐标对 描述空间地理数据。MongoDB使用 WGS84 参考系进行地理空间数据查询。 1、MongoDB支持空间数据的存储数据类型需要限制为GeoJSON; 2、MongoDB可以为GeoJSON类型数据建立索引提升空间查询的效率
1.2 GeoJSON对象 GeoJSON 对象格式 field: { type: GeoJSON type , coordinates: coordinates }
GeoJSON 对象有两个filed,分别是 type 和 coordinates.其中, type 指明是哪种空间地理数据类型 coordinates: 是描述 Geo对象的坐标数组,经度在前(经度取值范围 -180到 180),纬度在后(纬度取值范围是-90到90
二、功能演示操作
2.1 准备环境与初始数据 2.1.1、使用SpringBoot 和 MongoTemplate操作 增加MongoDB连接配置
spring:data:# MongoDB配置mongodb:uri: mongodb://usr:usrpassword192.168.xx.xx:27017/database: filedataauthentication-database: admin#自动创建索引auto-index-creation: trueconnections-num-min-size: 5connections-num-max-size: 10
2.1.2、创建GeoData对象存储空间数据
Data
ApiModel
Document(collection GEO-DATA)
public class GeoData {ApiModelProperty(name _id,value _id)private String _id;ApiModelProperty(name recordId,value recordId)private String recordId;ApiModelProperty(name name,value 名称)private String name;/** 经度 */ApiModelProperty(name lng,value 经度)private Double lng;/** 维度 */ApiModelProperty(name lat,value 维度)private Double lat;/*** 位置信息*/ApiModelProperty(name location,value 位置信息, hidden true)private GeoJsonPoint location;ApiModelProperty(name time,value 录入时间)private Long time;
}
2.1.3、增加集合GEO-DATA并创建对应的空间索引
db.getCollection(GEO-DATA).ensureIndex( { location :2dsphere } )
2.1.4、创建测试类MongoGeoTest
Slf4j
RunWith(SpringRunner.class)
SpringBootTest(classes Application.class, webEnvironment SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MongoGeoTest {Autowiredprivate MongoTemplate mongoTemplate;}
2.1.5、增加批量插入数据的方法 /*** 批量插入数据*/
public void batchInsertData() {//准备数据ListGeoData geoDataList new ArrayList();for (int i 0; i 10; i) {GeoData geoData new GeoData();geoData.setRecordId(UUID.fastUUID().toString(Boolean.TRUE));geoData.setName(RandomUtil.randomNumbers(12));geoData.setTime(new Date().getTime());//经度double lng 116.3180D RandomUtil.randomDouble(0.1d, 1.0d);geoData.setLng(lng);//维度double lat 39.9857D RandomUtil.randomDouble(0.1d, 1.0d);geoData.setLat(lat);geoData.setLocation(new GeoJsonPoint(lng, lat));geoDataList.add(geoData);}//保存数据Long start System.currentTimeMillis();mongoTemplate.insert(geoDataList, GEO-DATA);log.info(Mongo save documents to GEO-DATA 耗时{} 毫秒, System.currentTimeMillis() - start);
}2.2 多边形区域内查询 2.2.1、创建查询参数类MultiPositionPageQueryParam
Data
ApiModel
public class MultiPositionPageQueryParam {ApiModelProperty(name positions,value 位置集合)private ListBDSPosition positions;ApiModelProperty(name geoType, value 类型: 1-多点位置查询2-面区域查询)private Integer geoType;NotNullApiModelProperty(name pageNum,value pageNum 起始数字为 0)private Long pageNum;NotNullApiModelProperty(name pageSize,value pageSize)private Long pageSize;ApiModelProperty(name needCount,value 是否需要统计总记录数)private Boolean needCount Boolean.FALSE;
}
2.2.2、增加多边形区域查询方法
/*** 多边形区域内** param queryParam*/
public void queryGeoDataByMultiPositionPageQueryParam(MultiPositionPageQueryParam queryParam) {Query query new Query();Criteria criteria new Criteria();ListCriteria criteriaList new LinkedList();//过滤字段query.fields().include(recordId, _id, name, time, lng, lat, location);//位置集合过滤if (ObjectUtil.isNotNull(queryParam.getPositions()) queryParam.getPositions().size() 0) {// 类型: 1-多点位置查询2-面区域查询if (ObjectUtil.isNotNull(queryParam.getGeoType()) queryParam.getGeoType() 2 queryParam.getPositions().size() 2) {ListPoint pointList new LinkedList();//经纬度获取for (BDSPosition position : queryParam.getPositions()) {Point point new Point(position.getLng(), position.getLat());pointList.add(point);}pointList.add(pointList.get(0));GeoJsonPolygon geoJsonPolygon new GeoJsonPolygon(pointList);Criteria areaCriteria Criteria.where(location).within(geoJsonPolygon);query.addCriteria(areaCriteria);criteriaList.add(areaCriteria);} else {ListCriteria orCriteriaList new LinkedList();//经纬度判断for (BDSPosition position : queryParam.getPositions()) {orCriteriaList.add(Criteria.where(lng).is(position.getLng()).and(lat).is(position.getLat()));}Criteria orPositionCriteria new Criteria().orOperator(orCriteriaList);query.addCriteria(orPositionCriteria);criteriaList.add(orPositionCriteria);}}//总记录数统计Long total null;if (queryParam.getNeedCount()) {total mongoTemplate.findDistinct(query, recordId, GEO-DATA, String.class).stream().count();}//排序ListSort.Order orders new LinkedList();orders.add(Sort.Order.desc(time));AggregationOptions aggregationOptions AggregationOptions.builder().allowDiskUse(Boolean.TRUE).build();Aggregation aggregation null;if (criteriaList.size() 0) {criteria criteria.andOperator(criteriaList);aggregation Aggregation.newAggregation(Aggregation.project(recordId, _id, name, time, lng, lat, location),//查询条件Aggregation.match(criteria),//分组条件Aggregation.group(recordId).max(time).as(time).first(recordId).as(recordId).last(time).as(time),Aggregation.sort(Sort.by(orders)),//分页条件Aggregation.skip(queryParam.getPageNum()),Aggregation.limit(queryParam.getPageSize())).withOptions(aggregationOptions);} else {aggregation Aggregation.newAggregation(Aggregation.project(recordId, _id, name, time, lng, lat, location),//分组条件Aggregation.group(recordId).max(time).as(time).first(recordId).as(recordId).first(time).as(time),Aggregation.sort(Sort.by(orders)),//分页条件Aggregation.skip(queryParam.getPageNum()),Aggregation.limit(queryParam.getPageSize())).withOptions(aggregationOptions);}ListGeoData list mongoTemplate.aggregate(aggregation, GEO-DATA, GeoData.class).getMappedResults();log.info(Data: {}, list);
}
2.3 圆形区域内查询
2.3.1、创建查询参数类CirclePageQueryParam
Data
ApiModel
public class CirclePageQueryParam {NotNullApiModelProperty(name lng, value 经度)private Double lng;NotNullApiModelProperty(name lat, value 维度)private Double lat;NotNullApiModelProperty(name radius, value 半径)private Double radius;NotNullApiModelProperty(name pageNum,value pageNum 起始数字为 0)private Long pageNum;NotNullApiModelProperty(name pageSize,value pageSize)private Long pageSize;ApiModelProperty(name needCount,value 是否需要统计总记录数)private Boolean needCount Boolean.FALSE;
}
2.3.2、增加圆形区域查询方法
/*** 圆形区域内查询* param queryParam*/
public void queryGeoDataByCircle(CirclePageQueryParam queryParam) {Query query new Query();Criteria criteria new Criteria();ListCriteria criteriaList new LinkedList();//过滤字段query.fields().include(recordId, _id, name, time, lng, lat, location);//位置集合过滤if (ObjectUtil.isNotNull(queryParam.getLat()) ObjectUtil.isNotNull(queryParam.getLng()) ObjectUtil.isNotNull(queryParam.getRadius())) {Point point new Point(queryParam.getLng(), queryParam.getLat());Distance distance new Distance(queryParam.getRadius(), Metrics.MILES);Circle circle new Circle(point, distance);Criteria areaCriteria Criteria.where(location).withinSphere(circle);query.addCriteria(areaCriteria);criteriaList.add(areaCriteria);}else{log.info(参数有误必要参数为空。);return;}//总记录数统计Long total null;if (queryParam.getNeedCount()) {total mongoTemplate.findDistinct(query, recordId, GEO-DATA, String.class).stream().count();}//排序ListSort.Order orders new LinkedList();orders.add(Sort.Order.desc(time));AggregationOptions aggregationOptions AggregationOptions.builder().allowDiskUse(Boolean.TRUE).build();Aggregation aggregation null;if (criteriaList.size() 0) {criteria criteria.andOperator(criteriaList);aggregation Aggregation.newAggregation(Aggregation.project(recordId, _id, name, time, lng, lat, location),//查询条件Aggregation.match(criteria),//分组条件Aggregation.group(recordId).max(time).as(time).first(recordId).as(recordId).last(time).as(time),Aggregation.sort(Sort.by(orders)),//分页条件Aggregation.skip(queryParam.getPageNum()),Aggregation.limit(queryParam.getPageSize())).withOptions(aggregationOptions);} else {aggregation Aggregation.newAggregation(Aggregation.project(recordId, _id, name, time, lng, lat, location),//分组条件Aggregation.group(recordId).max(time).as(time).first(recordId).as(recordId).first(time).as(time),Aggregation.sort(Sort.by(orders)),//分页条件Aggregation.skip(queryParam.getPageNum()),Aggregation.limit(queryParam.getPageSize())).withOptions(aggregationOptions);}ListGeoData list mongoTemplate.aggregate(aggregation, GEO-DATA, GeoData.class).getMappedResults();log.info(Data: {}, list);
}