物流項目第九期(MongoDB的應用之作業范圍)

本項目專欄:

物流項目_Auc23的博客-CSDN博客

建議先看這期:

MongoDB入門之Java的使用-CSDN博客

需求分析?

在項目中,會有兩個作業范圍,分別是機構作業范圍和快遞員作業范圍,這兩個作業范圍的邏輯是一致的,就是在地圖中進行畫出范圍,就是其作業范圍。

實現分析?

對于作業范圍是一個由多個坐標點組成的多邊形,并且必須是閉合的多邊形,這個就比較適合用MongoDB來存儲。

現在想一個實際需求,用戶小王下了訂單,如何找到屬于該服務范圍內的快遞員呢?這個就需要使用MongoDB的$geoIntersects查詢操作,其原理就是查找小王的位置坐標點與哪個多邊形有交叉,這個就是為其服務的快遞員。

ServiceScopeEntity

/*** 服務范圍實體*/
@Data
@Document("sl_service_scope")
public class ServiceScopeEntity {@Id@JsonIgnoreprivate ObjectId id;/*** 業務id,可以是機構或快遞員*/@Indexedprivate Long bid;/*** 類型 {@link com.sl.ms.scope.enums.ServiceTypeEnum}*/@Indexedprivate Integer type;/*** 多邊形范圍,是閉合的范圍,開始經緯度與結束經緯度必須一樣* x: 經度,y:緯度*/@GeoSpatialIndexed(type = GeoSpatialIndexType.GEO_2DSPHERE)private GeoJsonPolygon polygon;private Long created; //創建時間private Long updated; //更新時間
}
/*** 服務類型枚舉*/
public enum ServiceTypeEnum {ORGAN(1, "機構"),COURIER(2, "快遞員");/*** 類型編碼*/private final Integer code;/*** 類型值*/private final String value;ServiceTypeEnum(Integer code, String value) {this.code = code;this.value = value;}public Integer getCode() {return code;}public String getValue() {return value;}public static ServiceTypeEnum codeOf(Integer code) {return EnumUtil.getBy(ServiceTypeEnum::getCode, code);}
}

ScopeService

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

  • 新增或更新服務范圍
  • 根據主鍵id刪除數據
  • 根據業務id和類型刪除數據
  • 根據主鍵查詢數據
  • 根據業務id和類型查詢數據
  • 根據坐標點查詢所屬的服務對象
  • 根據詳細地址查詢所屬的服務對象

/*** 服務范圍Service*/
public interface ScopeService {/*** 新增或更新服務范圍** @param bid     業務id* @param type    類型* @param polygon 多邊形坐標點* @return 是否成功*/Boolean saveOrUpdate(Long bid, ServiceTypeEnum type, GeoJsonPolygon polygon);/*** 根據主鍵id刪除數據** @param id 主鍵* @return 是否成功*/Boolean delete(String id);/*** 根據業務id和類型刪除數據** @param bid  業務id* @param type 類型* @return 是否成功*/Boolean delete(Long bid, ServiceTypeEnum type);/*** 根據主鍵查詢數據** @param id 主鍵* @return 服務范圍數據*/ServiceScopeEntity queryById(String id);/*** 根據業務id和類型查詢數據** @param bid  業務id* @param type 類型* @return 服務范圍數據*/ServiceScopeEntity queryByBidAndType(Long bid, ServiceTypeEnum type);/*** 根據坐標點查詢所屬的服務對象** @param type  類型* @param point 坐標點* @return 服務范圍數據*/List<ServiceScopeEntity> queryListByPoint(ServiceTypeEnum type, GeoJsonPoint point);/*** 根據詳細地址查詢所屬的服務對象** @param type    類型* @param address 詳細地址,如:北京市昌平區金燕龍辦公樓傳智教育總部* @return 服務范圍數據*/List<ServiceScopeEntity> queryListByPoint(ServiceTypeEnum type, String address);
}

?ScopeController

/*** 服務范圍*/
@Api(tags = "服務范圍")
@RestController
@RequestMapping("scopes")
@Validated
public class ScopeController {@Resourceprivate ScopeService scopeService;/*** 新增或更新服務服務范圍** @return REST標準響應*/@ApiOperation(value = "新增/更新", notes = "新增或更新服務服務范圍")@PostMappingpublic ResponseEntity<Void> saveScope(@RequestBody ServiceScopeDTO serviceScopeDTO) {ServiceScopeEntity serviceScopeEntity = EntityUtils.toEntity(serviceScopeDTO);Long bid = serviceScopeEntity.getBid();ServiceTypeEnum type = ServiceTypeEnum.codeOf(serviceScopeEntity.getType());Boolean result = this.scopeService.saveOrUpdate(bid, type, serviceScopeEntity.getPolygon());if (result) {return ResponseEntityUtils.ok();}return ResponseEntityUtils.error();}/*** 刪除服務范圍** @param bid  業務id* @param type 類型* @return REST標準響應*/@ApiImplicitParams({@ApiImplicitParam(name = "bid", value = "業務id,可以是機構或快遞員", dataTypeClass = Long.class),@ApiImplicitParam(name = "type", value = "類型,1-機構,2-快遞員", dataTypeClass = Integer.class)})@ApiOperation(value = "刪除", notes = "刪除服務范圍")@DeleteMapping("{bid}/{type}")public ResponseEntity<Void> delete(@NotNull(message = "bid不能為空") @PathVariable("bid") Long bid,@NotNull(message = "type不能為空") @PathVariable("type") Integer type) {Boolean result = this.scopeService.delete(bid, ServiceTypeEnum.codeOf(type));if (result) {return ResponseEntityUtils.ok();}return ResponseEntityUtils.error();}/*** 查詢服務范圍** @param bid  業務id* @param type 類型* @return 服務范圍數據*/@ApiImplicitParams({@ApiImplicitParam(name = "bid", value = "業務id,可以是機構或快遞員", dataTypeClass = Long.class),@ApiImplicitParam(name = "type", value = "類型,1-機構,2-快遞員", dataTypeClass = Integer.class)})@ApiOperation(value = "查詢", notes = "查詢服務范圍")@GetMapping("{bid}/{type}")public ResponseEntity<ServiceScopeDTO> queryServiceScope(@NotNull(message = "bid不能為空") @PathVariable("bid") Long bid,@NotNull(message = "type不能為空") @PathVariable("type") Integer type) {ServiceScopeEntity serviceScopeEntity = this.scopeService.queryByBidAndType(bid, ServiceTypeEnum.codeOf(type));return ResponseEntityUtils.ok(EntityUtils.toDTO(serviceScopeEntity));}/*** 地址查詢服務范圍** @param type    類型,1-機構,2-快遞員* @param address 詳細地址,如:北京市昌平區金燕龍辦公樓傳智教育總部* @return 服務范圍數據列表*/@ApiImplicitParams({@ApiImplicitParam(name = "type", value = "類型,1-機構,2-快遞員", dataTypeClass = Integer.class),@ApiImplicitParam(name = "address", value = "詳細地址,如:北京市昌平區金燕龍辦公樓傳智教育總部", dataTypeClass = String.class)})@ApiOperation(value = "地址查詢服務范圍", notes = "地址查詢服務范圍")@GetMapping("address")public ResponseEntity<List<ServiceScopeDTO>> queryListByAddress(@NotNull(message = "type不能為空") @RequestParam("type") Integer type,@NotNull(message = "address不能為空") @RequestParam("address") String address) {List<ServiceScopeEntity> serviceScopeEntityList = this.scopeService.queryListByPoint(ServiceTypeEnum.codeOf(type), address);return ResponseEntityUtils.ok(EntityUtils.toDTOList(serviceScopeEntityList));}/*** 位置查詢服務范圍** @param type      類型,1-機構,2-快遞員* @param longitude 經度* @param latitude  緯度* @return 服務范圍數據列表*/@ApiImplicitParams({@ApiImplicitParam(name = "type", value = "類型,1-機構,2-快遞員", dataTypeClass = Integer.class),@ApiImplicitParam(name = "longitude", value = "經度", dataTypeClass = Double.class),@ApiImplicitParam(name = "latitude", value = "緯度", dataTypeClass = Double.class)})@ApiOperation(value = "位置查詢服務范圍", notes = "位置查詢服務范圍")@GetMapping("location")public ResponseEntity<List<ServiceScopeDTO>> queryListByAddress(@NotNull(message = "type不能為空") @RequestParam("type") Integer type,@NotNull(message = "longitude不能為空") @RequestParam("longitude") Double longitude,@NotNull(message = "latitude不能為空") @RequestParam("latitude") Double latitude) {List<ServiceScopeEntity> serviceScopeEntityList = this.scopeService.queryListByPoint(ServiceTypeEnum.codeOf(type), new GeoJsonPoint(longitude, latitude));return ResponseEntityUtils.ok(EntityUtils.toDTOList(serviceScopeEntityList));}
}

實現接口


@Slf4j
@Service
public class ScopeServiceImpl implements ScopeService {@Resourceprivate MongoTemplate mongoTemplate;@Resourceprivate EagleMapTemplate eagleMapTemplate;@Overridepublic Boolean saveOrUpdate(Long bid, ServiceTypeEnum type, GeoJsonPolygon polygon) {Query query = Query.query(Criteria.where("bid").is(bid).and("type").is(type.getCode())); //構造查詢條件ServiceScopeEntity serviceScopeEntity = this.mongoTemplate.findOne(query, ServiceScopeEntity.class);if (ObjectUtil.isEmpty(serviceScopeEntity)) {//新增serviceScopeEntity = new ServiceScopeEntity();serviceScopeEntity.setBid(bid);serviceScopeEntity.setType(type.getCode());serviceScopeEntity.setPolygon(polygon);serviceScopeEntity.setCreated(System.currentTimeMillis());serviceScopeEntity.setUpdated(serviceScopeEntity.getCreated());} else {//更新serviceScopeEntity.setPolygon(polygon);serviceScopeEntity.setUpdated(System.currentTimeMillis());}try {this.mongoTemplate.save(serviceScopeEntity);return true;} catch (Exception e) {log.error("新增/更新服務范圍數據失敗! bid = {}, type = {}, points = {}", bid, type, polygon.getPoints(), e);}return false;}@Overridepublic Boolean delete(String id) {Query query = Query.query(Criteria.where("id").is(new ObjectId(id))); //構造查詢條件return this.mongoTemplate.remove(query, ServiceScopeEntity.class).getDeletedCount() > 0;}@Overridepublic Boolean delete(Long bid, ServiceTypeEnum type) {Query query = Query.query(Criteria.where("bid").is(bid).and("type").is(type.getCode())); //構造查詢條件return this.mongoTemplate.remove(query, ServiceScopeEntity.class).getDeletedCount() > 0;}@Overridepublic ServiceScopeEntity queryById(String id) {return this.mongoTemplate.findById(new ObjectId(id), ServiceScopeEntity.class);}@Overridepublic ServiceScopeEntity queryByBidAndType(Long bid, ServiceTypeEnum type) {Query query = Query.query(Criteria.where("bid").is(bid).and("type").is(type.getCode())); //構造查詢條件return this.mongoTemplate.findOne(query, ServiceScopeEntity.class);}@Overridepublic List<ServiceScopeEntity> queryListByPoint(ServiceTypeEnum type, GeoJsonPoint point) {Query query = Query.query(Criteria.where("polygon").intersects(point).and("type").is(type.getCode()));return this.mongoTemplate.find(query, ServiceScopeEntity.class);}@Overridepublic List<ServiceScopeEntity> queryListByPoint(ServiceTypeEnum type, String address) {//根據詳細地址查詢坐標GeoResult geoResult = this.eagleMapTemplate.opsForBase().geoCode(ProviderEnum.AMAP, address, null);Coordinate coordinate = geoResult.getLocation();return this.queryListByPoint(type, new GeoJsonPoint(coordinate.getLongitude(), coordinate.getLatitude()));}
}

測試

package com.sl.ms.scope.service;import com.sl.ms.scope.entity.ServiceScopeEntity;
import com.sl.ms.scope.enums.ServiceTypeEnum;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.geo.Point;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import org.springframework.data.mongodb.core.geo.GeoJsonPolygon;import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;@SpringBootTest
public class ScopeServiceTest {@Resourceprivate ScopeService scopeService;@Testvoid saveOrUpdate() {List<Point> pointList = Arrays.asList(new Point(116.340064,40.061245),new Point(116.347081,40.061836),new Point(116.34751,40.05842),new Point(116.342446,40.058092),new Point(116.340064,40.061245));Boolean result = this.scopeService.saveOrUpdate(2L, ServiceTypeEnum.ORGAN, new GeoJsonPolygon(pointList));System.out.println(result);}@Testvoid testQueryListByPoint() {GeoJsonPoint point = new GeoJsonPoint(116.344828,40.05911);List<ServiceScopeEntity> serviceScopeEntities = this.scopeService.queryListByPoint(ServiceTypeEnum.ORGAN, point);serviceScopeEntities.forEach(serviceScopeEntity -> System.out.println(serviceScopeEntity));}@Testvoid testQueryListByPoint2() {String address = "北京市昌平區金燕龍辦公樓";List<ServiceScopeEntity> serviceScopeEntities = this.scopeService.queryListByPoint(ServiceTypeEnum.ORGAN, address);serviceScopeEntities.forEach(serviceScopeEntity -> System.out.println(serviceScopeEntity));}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/82802.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/82802.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/82802.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

網絡拓撲如何跨網段訪問

最近領導讓研究下跟甲方合同里的&#xff0c;跨網段訪問怎么實現&#xff0c;之前不都是運維網工干的活么&#xff0c;看來裁員裁到動脈上了碰到用人的時候找不到人了&#xff0c; 只能趕鴨子上架讓我來搞 IP 網絡中&#xff0c;不同網段之間的通信需要通過路由器&#xff0c;…

【前端】PWA

目錄 概述實戰vue項目問題匯總 PWA&#xff08;漸進式 Web 應用&#xff0c;Progressive Web App&#xff09; 2015提出 概述 PWA 是一種提升 Web 應用體驗的技術&#xff0c;使其具備與原生應用相似的功能和性能。PWA不僅能夠在網頁上運行&#xff0c;還能在手機或桌面上像傳…

湖北理元理律師事務所:從法律合規到心靈契合的服務升維

債務優化不僅是數字游戲&#xff0c;更是信任重建的過程。湖北理元理律師事務所在實踐中發現&#xff1a;68%的債務糾紛中存在溝通斷裂。為此&#xff0c;機構構建了“三維信任修復機制”。 維度一&#xff1a;信息透明的技術實現 區塊鏈存證艙&#xff1a;客戶手機實時查看律…

香橙派3B學習筆記2:Vscode遠程SSH登錄香橙派_權限問題連接失敗解決

Vscode下載插件&#xff0c;ssh遠程登錄香橙派。 ssh &#xff1a; orangepi本地ip 密碼 &#xff1a; orangepi 安裝 Remote - SSH 擴展SSH插件&#xff1a; SSH遠程連接&#xff1a; ssh usernameremote_host ssh -p port_number usernameremote_host默認22端口號就用第一行…

VMware安裝Ubuntu實戰分享大綱

深入解析快速排序 一、分治策略分解 分解階段&#xff1a; 選擇基準元素 $pivot$將數組劃分為三個子集&#xff1a; $$ left {x | x < pivot} $$ $$ equal {x | x pivot} $$ $$ right {x | x > pivot} $$ 遞歸排序&#xff1a; 對 left 和 right 子集遞歸調用快速排…

AI 讓無人機跟蹤更精準——從視覺感知到智能預測

AI 讓無人機跟蹤更精準——從視覺感知到智能預測 無人機跟蹤技術正在經歷一場前所未有的變革。曾經,我們只能依靠 GPS 或簡單的視覺識別來跟蹤無人機,但如今,人工智能(AI)結合深度學習和高級視覺算法,正讓無人機的跟蹤變得更加智能化、精準化。 尤其是在自動駕駛、安防監…

GATED DELTA NETWORKS : IMPROVING MAMBA 2 WITH DELTA RULE

TL;DR 2024 年 Nvidia MIT 提出的線性Transformer 方法 Gated DeltaNet&#xff0c;融合了自適應內存控制的門控機制&#xff08;gating&#xff09;和用于精確內存修改的delta更新規則&#xff08;delta update rule&#xff09;&#xff0c;在多個基準測試中始終超越了現有…

Laravel單元測試使用示例

Date: 2025-05-28 17:35:46 author: lijianzhan 在 Laravel 框架中&#xff0c;單元測試是一種常用的測試方法&#xff0c;它是允許你測試應用程序中的最小可測試單元&#xff0c;通常是方法或函數。Laravel 提供了內置的測試工具PHPUnit&#xff0c;實踐中進行單元測試是保障代…

【FastAPI】--3.進階教程(二)

【FastAPI】--進階教程1-CSDN博客 【FastAPI】--基礎教程-CSDN博客 目錄 1.FastAPI - CORS ?2.FastAPI - CRUD 操作 2.1.Create 2.2.Read 2.3.Update 2.4.Delete 3.FastAPI - 使用 GraphQL 4.FastAPI - Websockets 5.FastAPI - 事件處理程序 6.FastAPI - 安裝 Fla…

FEMFAT許可的更新與升級流程

隨著工程仿真技術的不斷發展&#xff0c;FEMFAT作為一款領先的疲勞分析軟件&#xff0c;持續為用戶提供卓越的性能和創新的功能。為了保持軟件的最新性和高效性&#xff0c;了解FEMFAT許可的更新與升級流程至關重要。本文將為您詳細介紹FEMFAT許可的更新與升級流程&#xff0c;…

麒麟v10,arm64架構,編譯安裝Qt5.12.8

Window和麒麟x86_64架構&#xff0c;官網提供安裝包&#xff0c;麒麟arm64架構的&#xff0c;只能自己用編碼編譯安裝。 注意&#xff0c;“桌面”路徑是中文&#xff0c;所以不要把源碼放在桌面上編譯。 1. 下載源碼 從官網下載源碼&#xff1a;https://download.qt.io/arc…

20250528-C#知識:結構體

C#知識&#xff1a;結構體 結構體是一種自定義數據類型&#xff0c;用戶可以根據自身需求設計自己的結構體用來表示某種數據集合。結構體是一種值類型&#xff0c;結合了值類型的優點&#xff0c;避免了引用類型的缺點。本文簡單介紹并探究一下C#中的結構體。 結構體一般寫在命…

CRM系統的功能模塊劃分

基礎管理模塊 用戶管理 用戶注冊與登錄角色權限管理部門組織架構用戶信息管理 系統設置 基礎參數配置系統日志管理數據字典管理系統監控 客戶管理模塊 客戶信息管理 客戶基本信息客戶分類管理客戶標簽管理客戶關系圖譜 聯系人管理 聯系人信息聯系記錄溝通歷史重要日期提醒 …

Python中的跨域資源共享(CORS)處理

在Web開發中&#xff0c;跨域資源共享&#xff08;CORS&#xff09;是瀏覽器強制執行的安全機制&#xff0c;用于控制不同源&#xff08;協議域名端口&#xff09;之間的資源交互。下面我將通過Python示例詳細講解CORS的實現。 原生Python實現CORS Flask框架手動實現CORS fr…

Kruskal算法剖析與py/cpp/Java語言實現

Kruskal算法剖析與py/cpp/Java語言實現 一、Kruskal算法的基本概念1.1 最小生成樹1.2 Kruskal算法核心思想 二、Kruskal算法的執行流程三、Kruskal算法的代碼實現3.1 Python實現3.2 C實現3.3 Java實現 四、算法復雜度分析4.1 時間復雜度4.2 空間復雜度 五、Kruskal算法應用場景…

微信小程序返回上一頁監聽

本文實現的是微信小程序在返回上一頁時獲取通知并自定義業務。 最簡單的實現&#xff1a; 使用 wx.enableAlertBeforeUnload() 優點&#xff1a;快速接入 缺點&#xff1a;手勢不能識別、無法自定義彈窗內容&#xff08;僅詢問&#xff09; 方法二&#xff1a; page-conta…

Excel 統計某個字符串在指定區域出現的次數

【本文概要】 Excel 統計某個字符串在指定區域出現的次數&#xff1a; 1、Excel 統計一個單元格內的某字符串的出現次數 2、Excel 統計某一列所有單元格內的某字符串的出現次數 3、Excel 統計某一區域所有單元格內的某字符串的出現次數 1、Excel 統計一個單元格內的某字符串的出…

生物化學:藥品藥物 營養和補充劑信息 第三方認證信息 常見誤區 匯總

常見維生素和礦物質成分表 成分名稱好處副作用&#xff08;超量或敏感情況&#xff09;運作方式推薦日劑量&#xff08;成人&#xff09;劑量說明維生素A&#xff08;視黃醇&#xff09;視力、免疫、皮膚健康過量可致肝損傷、頭痛、脫發調節視網膜功能、細胞分化700–900 g RA…

mock庫知識筆記(持續更新)

文章目錄 mock簡介導入方式參數簡介使用場景&#xff08;待更新&#xff09;常見問題總結&#xff08;待更新&#xff09;Python代碼官網 mock簡介 mock是一個模擬對象庫&#xff0c;具有模擬其他python對象的功能&#xff0c;還能指定模擬對象的返回值和設置模擬對象的屬性。…

扇形 圓形 面積公式

? 一、圓的面積公式 全圓面積&#xff1a; A circle π r 2 A_{\text{circle}} \pi r^2 Acircle?πr2 ? 二、扇形的面積公式&#xff08;兩種制式&#xff09; 弧度制&#xff1a; A sector 1 2 r 2 θ A_{\text{sector}} \frac{1}{2} r^2 \theta Asector?21?r2θ …