物流项目第九期(MongoDB的应用之作业范围)

打印 上一主题 下一主题

主题 2061|帖子 2061|积分 6193

本项目专栏:
物流项目_Auc23的博客-CSDN博客
建议先看这期:
MongoDB入门之Java的利用-CSDN博客
需求分析 

在项目中,会有两个作业范围,分别是机构作业范围和快递员作业范围,这两个作业范围的逻辑是同等的,就是在地图中举行画出范围,就是其作业范围。

实现分析 

对于作业范围是一个由多个坐标点构成的多边形,并且必须是闭合的多边形,这个就比较适实用MongoDB来存储。
现在想一个实际需求,用户小王下了订单,如何找到属于该服务范围内的快递员呢?这个就必要利用MongoDB的$geoIntersects查询利用,其原理就是查找小王的位置坐标点与哪个多边形有交叉,这个就是为其服务的快递员。
ServiceScopeEntity

  1. /**
  2. * 服务范围实体
  3. */
  4. @Data
  5. @Document("sl_service_scope")
  6. public class ServiceScopeEntity {
  7.     @Id
  8.     @JsonIgnore
  9.     private ObjectId id;
  10.     /**
  11.      * 业务id,可以是机构或快递员
  12.      */
  13.     @Indexed
  14.     private Long bid;
  15.     /**
  16.      * 类型 {@link com.sl.ms.scope.enums.ServiceTypeEnum}
  17.      */
  18.     @Indexed
  19.     private Integer type;
  20.     /**
  21.      * 多边形范围,是闭合的范围,开始经纬度与结束经纬度必须一样
  22.      * x: 经度,y:纬度
  23.      */
  24.     @GeoSpatialIndexed(type = GeoSpatialIndexType.GEO_2DSPHERE)
  25.     private GeoJsonPolygon polygon;
  26.     private Long created; //创建时间
  27.     private Long updated; //更新时间
  28. }
复制代码
  1. /**
  2. * 服务类型枚举
  3. */
  4. public enum ServiceTypeEnum {
  5.     ORGAN(1, "机构"),
  6.     COURIER(2, "快递员");
  7.     /**
  8.      * 类型编码
  9.      */
  10.     private final Integer code;
  11.     /**
  12.      * 类型值
  13.      */
  14.     private final String value;
  15.     ServiceTypeEnum(Integer code, String value) {
  16.         this.code = code;
  17.         this.value = value;
  18.     }
  19.     public Integer getCode() {
  20.         return code;
  21.     }
  22.     public String getValue() {
  23.         return value;
  24.     }
  25.     public static ServiceTypeEnum codeOf(Integer code) {
  26.         return EnumUtil.getBy(ServiceTypeEnum::getCode, code);
  27.     }
  28. }
复制代码
ScopeService

   在ScopeService中主要定义了如下方法:
  

  • 新增或更新服务范围
  • 根据主键id删除数据
  • 根据业务id和范例删除数据
  • 根据主键查询数据
  • 根据业务id和范例查询数据
  • 根据坐标点查询所属的服务对象
  • 根据详细地点查询所属的服务对象
  1. /**
  2. * 服务范围Service
  3. */
  4. public interface ScopeService {
  5.     /**
  6.      * 新增或更新服务范围
  7.      *
  8.      * @param bid     业务id
  9.      * @param type    类型
  10.      * @param polygon 多边形坐标点
  11.      * @return 是否成功
  12.      */
  13.     Boolean saveOrUpdate(Long bid, ServiceTypeEnum type, GeoJsonPolygon polygon);
  14.     /**
  15.      * 根据主键id删除数据
  16.      *
  17.      * @param id 主键
  18.      * @return 是否成功
  19.      */
  20.     Boolean delete(String id);
  21.     /**
  22.      * 根据业务id和类型删除数据
  23.      *
  24.      * @param bid  业务id
  25.      * @param type 类型
  26.      * @return 是否成功
  27.      */
  28.     Boolean delete(Long bid, ServiceTypeEnum type);
  29.     /**
  30.      * 根据主键查询数据
  31.      *
  32.      * @param id 主键
  33.      * @return 服务范围数据
  34.      */
  35.     ServiceScopeEntity queryById(String id);
  36.     /**
  37.      * 根据业务id和类型查询数据
  38.      *
  39.      * @param bid  业务id
  40.      * @param type 类型
  41.      * @return 服务范围数据
  42.      */
  43.     ServiceScopeEntity queryByBidAndType(Long bid, ServiceTypeEnum type);
  44.     /**
  45.      * 根据坐标点查询所属的服务对象
  46.      *
  47.      * @param type  类型
  48.      * @param point 坐标点
  49.      * @return 服务范围数据
  50.      */
  51.     List<ServiceScopeEntity> queryListByPoint(ServiceTypeEnum type, GeoJsonPoint point);
  52.     /**
  53.      * 根据详细地址查询所属的服务对象
  54.      *
  55.      * @param type    类型
  56.      * @param address 详细地址,如:北京市昌平区金燕龙办公楼传智教育总部
  57.      * @return 服务范围数据
  58.      */
  59.     List<ServiceScopeEntity> queryListByPoint(ServiceTypeEnum type, String address);
  60. }
复制代码
 ScopeController

  1. /**
  2. * 服务范围
  3. */
  4. @Api(tags = "服务范围")
  5. @RestController
  6. @RequestMapping("scopes")
  7. @Validated
  8. public class ScopeController {
  9.     @Resource
  10.     private ScopeService scopeService;
  11.     /**
  12.      * 新增或更新服务服务范围
  13.      *
  14.      * @return REST标准响应
  15.      */
  16.     @ApiOperation(value = "新增/更新", notes = "新增或更新服务服务范围")
  17.     @PostMapping
  18.     public ResponseEntity<Void> saveScope(@RequestBody ServiceScopeDTO serviceScopeDTO) {
  19.         ServiceScopeEntity serviceScopeEntity = EntityUtils.toEntity(serviceScopeDTO);
  20.         Long bid = serviceScopeEntity.getBid();
  21.         ServiceTypeEnum type = ServiceTypeEnum.codeOf(serviceScopeEntity.getType());
  22.         Boolean result = this.scopeService.saveOrUpdate(bid, type, serviceScopeEntity.getPolygon());
  23.         if (result) {
  24.             return ResponseEntityUtils.ok();
  25.         }
  26.         return ResponseEntityUtils.error();
  27.     }
  28.     /**
  29.      * 删除服务范围
  30.      *
  31.      * @param bid  业务id
  32.      * @param type 类型
  33.      * @return REST标准响应
  34.      */
  35.     @ApiImplicitParams({
  36.             @ApiImplicitParam(name = "bid", value = "业务id,可以是机构或快递员", dataTypeClass = Long.class),
  37.             @ApiImplicitParam(name = "type", value = "类型,1-机构,2-快递员", dataTypeClass = Integer.class)
  38.     })
  39.     @ApiOperation(value = "删除", notes = "删除服务范围")
  40.     @DeleteMapping("{bid}/{type}")
  41.     public ResponseEntity<Void> delete(@NotNull(message = "bid不能为空") @PathVariable("bid") Long bid,
  42.                                        @NotNull(message = "type不能为空") @PathVariable("type") Integer type) {
  43.         Boolean result = this.scopeService.delete(bid, ServiceTypeEnum.codeOf(type));
  44.         if (result) {
  45.             return ResponseEntityUtils.ok();
  46.         }
  47.         return ResponseEntityUtils.error();
  48.     }
  49.     /**
  50.      * 查询服务范围
  51.      *
  52.      * @param bid  业务id
  53.      * @param type 类型
  54.      * @return 服务范围数据
  55.      */
  56.     @ApiImplicitParams({
  57.             @ApiImplicitParam(name = "bid", value = "业务id,可以是机构或快递员", dataTypeClass = Long.class),
  58.             @ApiImplicitParam(name = "type", value = "类型,1-机构,2-快递员", dataTypeClass = Integer.class)
  59.     })
  60.     @ApiOperation(value = "查询", notes = "查询服务范围")
  61.     @GetMapping("{bid}/{type}")
  62.     public ResponseEntity<ServiceScopeDTO> queryServiceScope(@NotNull(message = "bid不能为空") @PathVariable("bid") Long bid,
  63.                                                              @NotNull(message = "type不能为空") @PathVariable("type") Integer type) {
  64.         ServiceScopeEntity serviceScopeEntity = this.scopeService.queryByBidAndType(bid, ServiceTypeEnum.codeOf(type));
  65.         return ResponseEntityUtils.ok(EntityUtils.toDTO(serviceScopeEntity));
  66.     }
  67.     /**
  68.      * 地址查询服务范围
  69.      *
  70.      * @param type    类型,1-机构,2-快递员
  71.      * @param address 详细地址,如:北京市昌平区金燕龙办公楼传智教育总部
  72.      * @return 服务范围数据列表
  73.      */
  74.     @ApiImplicitParams({
  75.             @ApiImplicitParam(name = "type", value = "类型,1-机构,2-快递员", dataTypeClass = Integer.class),
  76.             @ApiImplicitParam(name = "address", value = "详细地址,如:北京市昌平区金燕龙办公楼传智教育总部", dataTypeClass = String.class)
  77.     })
  78.     @ApiOperation(value = "地址查询服务范围", notes = "地址查询服务范围")
  79.     @GetMapping("address")
  80.     public ResponseEntity<List<ServiceScopeDTO>> queryListByAddress(@NotNull(message = "type不能为空") @RequestParam("type") Integer type,
  81.                                                                     @NotNull(message = "address不能为空") @RequestParam("address") String address) {
  82.         List<ServiceScopeEntity> serviceScopeEntityList = this.scopeService.queryListByPoint(ServiceTypeEnum.codeOf(type), address);
  83.         return ResponseEntityUtils.ok(EntityUtils.toDTOList(serviceScopeEntityList));
  84.     }
  85.     /**
  86.      * 位置查询服务范围
  87.      *
  88.      * @param type      类型,1-机构,2-快递员
  89.      * @param longitude 经度
  90.      * @param latitude  纬度
  91.      * @return 服务范围数据列表
  92.      */
  93.     @ApiImplicitParams({
  94.             @ApiImplicitParam(name = "type", value = "类型,1-机构,2-快递员", dataTypeClass = Integer.class),
  95.             @ApiImplicitParam(name = "longitude", value = "经度", dataTypeClass = Double.class),
  96.             @ApiImplicitParam(name = "latitude", value = "纬度", dataTypeClass = Double.class)
  97.     })
  98.     @ApiOperation(value = "位置查询服务范围", notes = "位置查询服务范围")
  99.     @GetMapping("location")
  100.     public ResponseEntity<List<ServiceScopeDTO>> queryListByAddress(@NotNull(message = "type不能为空") @RequestParam("type") Integer type,
  101.                                                                     @NotNull(message = "longitude不能为空") @RequestParam("longitude") Double longitude,
  102.                                                                     @NotNull(message = "latitude不能为空") @RequestParam("latitude") Double latitude) {
  103.         List<ServiceScopeEntity> serviceScopeEntityList = this.scopeService.queryListByPoint(ServiceTypeEnum.codeOf(type), new GeoJsonPoint(longitude, latitude));
  104.         return ResponseEntityUtils.ok(EntityUtils.toDTOList(serviceScopeEntityList));
  105.     }
  106. }
复制代码
实现接口

  1. @Slf4j
  2. @Service
  3. public class ScopeServiceImpl implements ScopeService {
  4.     @Resource
  5.     private MongoTemplate mongoTemplate;
  6.     @Resource
  7.     private EagleMapTemplate eagleMapTemplate;
  8.     @Override
  9.     public Boolean saveOrUpdate(Long bid, ServiceTypeEnum type, GeoJsonPolygon polygon) {
  10.         Query query = Query.query(Criteria.where("bid").is(bid).and("type").is(type.getCode())); //构造查询条件
  11.         ServiceScopeEntity serviceScopeEntity = this.mongoTemplate.findOne(query, ServiceScopeEntity.class);
  12.         if (ObjectUtil.isEmpty(serviceScopeEntity)) {
  13.             //新增
  14.             serviceScopeEntity = new ServiceScopeEntity();
  15.             serviceScopeEntity.setBid(bid);
  16.             serviceScopeEntity.setType(type.getCode());
  17.             serviceScopeEntity.setPolygon(polygon);
  18.             serviceScopeEntity.setCreated(System.currentTimeMillis());
  19.             serviceScopeEntity.setUpdated(serviceScopeEntity.getCreated());
  20.         } else {
  21.             //更新
  22.             serviceScopeEntity.setPolygon(polygon);
  23.             serviceScopeEntity.setUpdated(System.currentTimeMillis());
  24.         }
  25.         try {
  26.             this.mongoTemplate.save(serviceScopeEntity);
  27.             return true;
  28.         } catch (Exception e) {
  29.             log.error("新增/更新服务范围数据失败! bid = {}, type = {}, points = {}", bid, type, polygon.getPoints(), e);
  30.         }
  31.         return false;
  32.     }
  33.     @Override
  34.     public Boolean delete(String id) {
  35.         Query query = Query.query(Criteria.where("id").is(new ObjectId(id))); //构造查询条件
  36.         return this.mongoTemplate.remove(query, ServiceScopeEntity.class).getDeletedCount() > 0;
  37.     }
  38.     @Override
  39.     public Boolean delete(Long bid, ServiceTypeEnum type) {
  40.         Query query = Query.query(Criteria.where("bid").is(bid).and("type").is(type.getCode())); //构造查询条件
  41.         return this.mongoTemplate.remove(query, ServiceScopeEntity.class).getDeletedCount() > 0;
  42.     }
  43.     @Override
  44.     public ServiceScopeEntity queryById(String id) {
  45.         return this.mongoTemplate.findById(new ObjectId(id), ServiceScopeEntity.class);
  46.     }
  47.     @Override
  48.     public ServiceScopeEntity queryByBidAndType(Long bid, ServiceTypeEnum type) {
  49.         Query query = Query.query(Criteria.where("bid").is(bid).and("type").is(type.getCode())); //构造查询条件
  50.         return this.mongoTemplate.findOne(query, ServiceScopeEntity.class);
  51.     }
  52.     @Override
  53.     public List<ServiceScopeEntity> queryListByPoint(ServiceTypeEnum type, GeoJsonPoint point) {
  54.         Query query = Query.query(Criteria.where("polygon").intersects(point)
  55.                 .and("type").is(type.getCode()));
  56.         return this.mongoTemplate.find(query, ServiceScopeEntity.class);
  57.     }
  58.     @Override
  59.     public List<ServiceScopeEntity> queryListByPoint(ServiceTypeEnum type, String address) {
  60.         //根据详细地址查询坐标
  61.         GeoResult geoResult = this.eagleMapTemplate.opsForBase().geoCode(ProviderEnum.AMAP, address, null);
  62.         Coordinate coordinate = geoResult.getLocation();
  63.         return this.queryListByPoint(type, new GeoJsonPoint(coordinate.getLongitude(), coordinate.getLatitude()));
  64.     }
  65. }
复制代码
测试

  1. package com.sl.ms.scope.service;
  2. import com.sl.ms.scope.entity.ServiceScopeEntity;
  3. import com.sl.ms.scope.enums.ServiceTypeEnum;
  4. import org.junit.jupiter.api.Test;
  5. import org.springframework.boot.test.context.SpringBootTest;
  6. import org.springframework.data.geo.Point;
  7. import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
  8. import org.springframework.data.mongodb.core.geo.GeoJsonPolygon;
  9. import javax.annotation.Resource;
  10. import java.util.Arrays;
  11. import java.util.List;
  12. @SpringBootTest
  13. public class ScopeServiceTest {
  14.     @Resource
  15.     private ScopeService scopeService;
  16.     @Test
  17.     void saveOrUpdate() {
  18.         List<Point> pointList = Arrays.asList(new Point(116.340064,40.061245),
  19.                 new Point(116.347081,40.061836),
  20.                 new Point(116.34751,40.05842),
  21.                 new Point(116.342446,40.058092),
  22.                 new Point(116.340064,40.061245));
  23.         Boolean result = this.scopeService.saveOrUpdate(2L, ServiceTypeEnum.ORGAN, new GeoJsonPolygon(pointList));
  24.         System.out.println(result);
  25.     }
  26.     @Test
  27.     void testQueryListByPoint() {
  28.         GeoJsonPoint point = new GeoJsonPoint(116.344828,40.05911);
  29.         List<ServiceScopeEntity> serviceScopeEntities = this.scopeService.queryListByPoint(ServiceTypeEnum.ORGAN, point);
  30.         serviceScopeEntities.forEach(serviceScopeEntity -> System.out.println(serviceScopeEntity));
  31.     }
  32.     @Test
  33.     void testQueryListByPoint2() {
  34.         String address = "北京市昌平区金燕龙办公楼";
  35.         List<ServiceScopeEntity> serviceScopeEntities = this.scopeService.queryListByPoint(ServiceTypeEnum.ORGAN, address);
  36.         serviceScopeEntities.forEach(serviceScopeEntity -> System.out.println(serviceScopeEntity));
  37.     }
  38. }
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

篮之新喜

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表