目錄
前言
一、百度POI分類簡介
1、數據表格
?2、分類結構
二、從Excel導入到PG數據庫
1、Excel解析流程
2、數據入庫
3、入庫成果及檢索
三、總結
前言
????????在上一篇博文中,我們對高德POI分類進行了深入剖析 并對Excel 中 POI 分類數據的存儲結構特點進行了詳細介紹,針對美食、電影院等不同分類數據字段特性,還將著重探索如何優化導入流程,基于ApachePOI實現高德POI分類快速導入PostgreSQL數據庫實戰。除了高德地圖之外,還有百度開放地圖也同樣提供POI的檢索服務,與之配套的也還有POI分類的管理。但是兩個POI的分類存在非常大的差異,層次結構也是不一樣的。如下圖:
????????百度地圖的POI分類從大類來說就跟高德POI不一樣,單從一級大類的數量來說,百度擁有?32個,而高德只區分了25個,不僅如何,從層級上來說,高德通常只區分了3即分類,而百度竟然有5級分類。那么本文即來重點講講百度POI分類與高德POI分類存在什么不一樣的地方,同時深入講解開百度?POI 分類如何進行數據導入,也為各類基于 POI 分類數據的地理信息系統開發、商業智能分析以及城市規劃應用等,鋪設一條從數據獲取到存儲利用的高效路徑,助力行業在空間數據賦能下實現精準決策與創新發展。
一、百度POI分類簡介
????????本節將首先重點介紹百度地圖的POI分類信息,在之前的博客中我們設計了用于POI管理的物理表,希望可以用來存儲對應的POI分類信息。然后使用數據庫腳本的方法對POI分類信息進行錄入管理。而對于百度地圖而言,其POI的分類是非常詳細的,因此這一節我們來詳細的解讀一下百度的POI分類,讓大家對分類信息有進一步的了解,為下一步數據的批量解析入庫打下牢固的基礎。
1、數據表格
? ? ? ? 與之前介紹的內容一樣,大家可以從百度的地圖開放平臺中獲取其最新的POI分類的Excel表格,這里我將從官網下載的類型截取一部分給大家參考,這里不進行贅述,需要原始Excel表格的,可以去網站上下載。
????????從上面這張圖可以看出,百度地圖的POI分類確實分的比較細,比較符合一些細粒度的區分,比如如果有一個場景需要區分歷史博物館和海洋博物館等,如果使用的是百度的API來進行檢索,那么是比較容易進行行業細分的。 同時也能看到一個比較明顯的區別,在百度的POI分類中,在它的五級分類管理體系中,其分類沒有編碼的概念,也沒有對應的英文,當然,編碼只是一個邏輯編碼,并不代表嚴格的含義,最主要的還是分類的名稱,這才是最重要的。
????????同樣的,基于百度地圖的POI檢索可以從返回接口中看到其對應的POI分類值為:
{"name":"千佛洞景區","location":{"lat":28.220183,"lng":112.148422},"address":"長沙市寧鄉市104縣道(近天紫漂流)","province":"湖南省","city":"長沙市","area":"寧鄉市","street_id":"","telephone":"(0731)87550989","detail":1,"uid":"5b25f44687acb9ea1029352c","detail_info":{"classified_poi_tag":"旅游景點;自然景觀;風景區","new_alias":"寧鄉千佛洞","tag":"旅游景點;風景區","navi_location":{"lng":112.14478762174,"lat":28.220406186348},"type":"scope","detail_url":"http://api.map.baidu.com/place/detail?uid=5b25f44687acb9ea1029352c&output=html&source=placeapi_v2","overall_rating":"4.4","comment_num":"56","shop_hours":"08:00-18:00","label":"AAAA景區,洞穴"}
}
??????????其中classified_poi_tag對應poi分類的類別。
?2、分類結構
????????在了解了百度地圖的POI分類之后,下面我們基于之前設計的數據庫物理表和分類信息構建樹形的信息。因此需要對其分類采取細致的分類管理。在進行樹形層次構建時,我們根據分類名稱來進行統一管理:
????????這個結構是百度POI分類管理的基礎,也是后面的數據程序解析的基礎。我們將使用編碼來進行五級分類的解析及入庫。 在Excel中,很大的大類和種類都是重復的,因此需要在入庫時將類別進行去重分類,最終構建一棵完整的POI分類樹。 與高德POI分類不一樣的是,百度的POI分類在層次上不是不一樣的,不僅在層級上比高德多兩極。同時存在為空的情況,并不是所有的POI分類都可以分成5級。
二、從Excel導入到PG數據庫
????????本節將詳細介紹在Java中使用ApachePOI實現從Excel中解析到存儲至PostgreSQL中,主要包含兩個方面,第一個是如何結合POI分類的規則進行分類解析。第二個方面是如何基于Mybatis實現程序的批量入庫。完整的數據處理流程與高德POI入庫的流程一致,基本分為三個步驟:第一步是批量讀取Excel,第二步是將Excel解析出POI分類數據,最后將分類好的數據導入到PG數據庫中。由于百度地圖和高德地圖的層級存在很大的差距,因此這里著重介紹如何動態構建百度的層級樹。
1、Excel解析流程
? ? ? ? 首先還是對百度Excel的POI分類進行解析,在進行POI的分類進行構建時尤其重要,為了防止各層級在構建時出現重復的情況,這里采用LinkedHashMap集合來進行重復判斷,在存儲集合對象時,將分類編碼作為map的key,而具體分類對象作為value。在后續的對象去重判斷時,key就是重復的標記。為了實現Excel數據的導入,需要定義一個JavaBean來讀取數據,其關鍵代碼如下:????????
package com.yelang.project.poisubject.poi.domain;
import java.io.Serializable;
import com.yelang.framework.aspectj.lang.annotation.Excel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/*** - 百度POI分類Excel視圖對象* @author 夜郎king*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class BaiduPoiCategoryExcelVO implements Serializable{private static final long serialVersionUID = -4167642920886200649L;@Excel(name = "一級")private String levelFirst;//一級@Excel(name = "二級")private String levelSecond;//二級@Excel(name = "三級")private String levelThird;//三級@Excel(name = "四級")private String levelFourth;//四級@Excel(name = "五級")private String levelFifth;//五級
}
????????與高德POI分類的Excel解析對象類似的是,這里的屬性定義與Excel表格中的單元格需要逐一對應方可解析。?接下來讀取Excel的數據,按照分類對百度POI分類進行層級重建,與高德的三級分類不同的是,百度地圖有五級分類,需要進行五級分類的檢驗,核心代碼如下:
File file = new File(BAIDU_POI_FILE);
FileInputStream fis = new FileInputStream(file);
ExcelUtil<BaiduPoiCategoryExcelVO> util = new ExcelUtil<BaiduPoiCategoryExcelVO>(BaiduPoiCategoryExcelVO.class);
List<BaiduPoiCategoryExcelVO> dataList = util.importExcel(fis);
LinkedHashMap<String,PoiCategory> amapPoiTypeMap = new LinkedHashMap<String, PoiCategory>();
for(BaiduPoiCategoryExcelVO poiCategory : dataList) {String levelFirst = poiCategory.getLevelFirst();//處理一級,添加到集合中if(!amapPoiTypeMap.containsKey(levelFirst)) {PoiCategory category = new PoiCategory(IdWorker.getId(),102L,"0,100,102",levelFirst,StringUtils.EMPTY,StringUtils.EMPTY);amapPoiTypeMap.put(levelFirst, category);}//處理二級,添加到集合中String levelSecond = poiCategory.getLevelSecond();if(com.yelang.common.utils.StringUtils.isEmpty(levelSecond)) {continue;}String keySecond = levelFirst + "-" + levelSecond;if(!amapPoiTypeMap.containsKey(keySecond)) {PoiCategory parentCategory = amapPoiTypeMap.get(levelFirst);String ancestors = parentCategory.getAncestors() + "," + parentCategory.getPkId();PoiCategory category = new PoiCategory(IdWorker.getId(),parentCategory.getPkId(),ancestors,levelSecond,StringUtils.EMPTY,StringUtils.EMPTY);amapPoiTypeMap.put(keySecond, category);} //處理三級String levelThird = poiCategory.getLevelThird();if(com.yelang.common.utils.StringUtils.isEmpty(levelThird)) {continue;}String keyThird = keySecond + "-" + levelThird;if(!amapPoiTypeMap.containsKey(keyThird)) {PoiCategory parentCategory = amapPoiTypeMap.get(keySecond);String ancestors = parentCategory.getAncestors() + "," + parentCategory.getPkId();PoiCategory category = new PoiCategory(IdWorker.getId(),parentCategory.getPkId(),ancestors,levelThird,StringUtils.EMPTY,StringUtils.EMPTY);amapPoiTypeMap.put(keyThird, category);} //處理四級String levelFourth = poiCategory.getLevelFourth();if(com.yelang.common.utils.StringUtils.isEmpty(levelFourth)) {continue;}String keyFourth = keyThird + "-" + levelFourth;if(!amapPoiTypeMap.containsKey(keyFourth)) {PoiCategory parentCategory = amapPoiTypeMap.get(keyThird);String ancestors = parentCategory.getAncestors() + "," + parentCategory.getPkId();PoiCategory category = new PoiCategory(IdWorker.getId(),parentCategory.getPkId(),ancestors,levelFourth,StringUtils.EMPTY,StringUtils.EMPTY);amapPoiTypeMap.put(keyFourth, category);} //處理五級String levelFifth = poiCategory.getLevelFifth();if(com.yelang.common.utils.StringUtils.isEmpty(levelFifth)) {continue;}String keylevelFifth = keyFourth + "-" + levelFifth;if(!amapPoiTypeMap.containsKey(keylevelFifth)) {PoiCategory parentCategory = amapPoiTypeMap.get(keyFourth);String ancestors = parentCategory.getAncestors() + "," + parentCategory.getPkId();PoiCategory category = new PoiCategory(IdWorker.getId(),parentCategory.getPkId(),ancestors,levelFifth,StringUtils.EMPTY,StringUtils.EMPTY);amapPoiTypeMap.put(keylevelFifth, category);}
}
????????在樹形結構的構造過程當中,需要注意map中key的構建,與高德不一樣的是,百度地圖沒有分類編碼的設置,因此我們直接使用分類名稱,在父子層級中將分類按照“-”進行連接作為組裝,以此來構建一棵完整的分類層級樹。
2、數據入庫
????????對于Mybatis的批量入庫方法與高德POI入庫的方法一致,均是采用Mybatis的批量入庫方法。再次不進行重復敘述。在設置POI分類數據源的時候,需要區分所屬平臺,比如百度或者高德,這里需要進行一個設置。調用批量入庫和統一屬性的設置方法如下:
List<PoiCategory> categoryData = new ArrayList<PoiCategory>();
for (PoiCategory value : amapPoiTypeMap.values()) {value.setPlatform("baidu");value.setDelFlag(0);value.setStatus(0);value.setOrderNum(1);value.setCreateTime(DateUtils.getNowDate());categoryData.add(value);
}
poiCateGoryService.batchInsertPoiCategory(categoryData);
//數據入庫
System.out.println("finished...");
3、入庫成果及檢索
????????完成以上的操作后就完成了百度POI分類數據的Postgresql數據庫導入操作,程序執行完成后,可以在控制臺看到以下輸出:
????????說明Excel成功被解析,并將數據持久化到了數據庫之中。為了驗證是否在數據庫中是否也保存了這些數據,可以使用以下SQL語句進行查詢:
select * from biz_poi_category where parent_id = 102;
????????在客戶端軟件中執行以上SQL后可以看到以下結果:
三、總結
????????以上就是本文的主要內容,支持對于高德地圖和百度地圖的POI分類的Excel入庫及檢索就基本完成,后續我們將深入使用兩者的POI信息以及如何進行相應數據的采集。那么本文即來重點講講百度POI分類與高德POI分類存在什么不一樣的地方,同時深入講解開百度?POI 分類如何進行數據導入,也為各類基于 POI 分類數據的地理信息系統開發、商業智能分析以及城市規劃應用等,鋪設一條從數據獲取到存儲利用的高效路徑,助力行業在空間數據賦能下實現精準決策與創新發展。行文倉促,難免有許多不足之處,如有不足,在此懇請各位專家博主在評論區不吝留言指出,不勝感激。