ES 使用geo point 查詢離目標地址最近的數據

? ? ? ? 需求描述:項目中需要通過經緯度坐標查詢目標地所在的行政區。

? ? ? ? 解決思路大致有種,使用es和mysql分別查詢。? ?

? ? 1、使用es進行查詢

????????將帶有經緯度坐標的省市區數據存入es中,mappings字段使用geo point類型,索引及查詢dsl如下。

? ? ? ? geo point文檔地址:
????????????????Geo-distance query | Elasticsearch Guide [8.6] | Elastic

????????????????Sort search results | Elasticsearch Guide [8.6] | Elastic

? ? ? ? mappings結構:

PUT /sys_district
{"settings": {"index": {"number_of_shards": 1,"number_of_replicas": 1}},"mappings": {"properties": {"id": {"type": "long"},"parent_id": {"type": "long"},"name": {"type": "keyword"},"zipcode": {"type": "integer"},"pinyin": {"type": "keyword"},"location": {"type": "geo_point" // 如果用于地理坐標,可以考慮使用 geo_point 類型},"level": {"type": "byte" },"sort": {"type": "byte"}}}
}

????????dsl語句:

# 搜索坐標點附近的數據
GET sys_district/_search
{"from": 0,"size": 3,"query": {"bool": {"must": {"match_all": {}},"filter": [{"geo_distance": {# 半徑內距離限制"distance": "100km","location": {# 目的地坐標"lat": 34.4328,"lon": 115.88}}},{"term": {"level": "3"}}]}},
# 排序"sort" : [{"_geo_distance" : {"location" : {"lat" :  34.4328,"lon" :115.88},"order" : "asc","unit" : "km"}}]
}

? ? ? ? 獲取舉例最近的排序不能漏了

?2、使用mysql進行查詢

????????將帶有經緯度坐標的省市區數據存入mysql中,使用mysql直接計算,表結構及查詢sql如下。

????????表結構:

CREATE TABLE `sys_district` (`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ID',`parent_id` INT(10) UNSIGNED NOT NULL COMMENT '父欄目',`name` VARCHAR(50) NOT NULL DEFAULT '' COLLATE 'utf8_general_ci',`zipcode` INT(10) UNSIGNED NOT NULL DEFAULT '0',`pinyin` VARCHAR(100) NOT NULL DEFAULT '' COLLATE 'utf8_general_ci',`lng` VARCHAR(20) NOT NULL DEFAULT '' COLLATE 'utf8_general_ci',`lat` VARCHAR(20) NOT NULL DEFAULT '' COLLATE 'utf8_general_ci',`level` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0',`sort` TINYINT(3) UNSIGNED NOT NULL DEFAULT '50' COMMENT '排序',`location` VARCHAR(255) NOT NULL DEFAULT '' COLLATE 'utf8_general_ci',PRIMARY KEY (`id`) USING BTREE
)
COMMENT='(公共)區域數據'
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;

? ? ? ? 查詢sql:?

SELECT * FROM sys_district WHERE ABS(lat - 34.4328) + ABS(lng - 115.88) = (SELECT MIN(ABS(lng - 115.88) + ABS(lat - 34.4328)) FROM sys_district ) LIMIT 1;

? ? ? ? 使用mysql計算可優化的地方在于,新版本mysql提供了空間幾何字段類型POINT,優化后新表結構如下。

CREATE TABLE `sys_district` (`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ID',`parent_id` INT(10) UNSIGNED NOT NULL COMMENT '父欄目',`name` VARCHAR(50) NOT NULL DEFAULT '' COLLATE 'utf8mb3_general_ci',`zipcode` INT(10) UNSIGNED NOT NULL DEFAULT '0',`pinyin` VARCHAR(100) NOT NULL DEFAULT '' COLLATE 'utf8mb3_general_ci',`lng` VARCHAR(20) NOT NULL DEFAULT '' COLLATE 'utf8mb3_general_ci',`lat` VARCHAR(20) NOT NULL DEFAULT '' COLLATE 'utf8mb3_general_ci',`geom` POINT NOT NULL COMMENT 'geo',`level` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0',`sort` TINYINT(3) UNSIGNED NOT NULL DEFAULT '50' COMMENT '排序',`location` VARCHAR(255) NOT NULL DEFAULT '' COLLATE 'utf8mb3_general_ci',PRIMARY KEY (`id`) USING BTREE,SPATIAL INDEX `geom` (`geom`)
)
COMMENT='(公共)區域數據'
COLLATE='utf8mb3_general_ci'
ENGINE=InnoDB
;

? ? ? ? 字段設置:

ALTER TABLE `sys_district`ADD COLUMN `geom` POINT NULL AFTER `lat`;UPDATE sys_district SET geom = ST_PointFromText(CONCAT('POINT(', lng, ' ', lat, ')')) ;ALTER TABLE sys_district ADD SPATIAL INDEX(geom);

? ? ? ? 查詢sql如下:

????????ST_PointFromText(CONCAT('POINT(', lng, ' ', lat, ')'))?將表中的經度和緯度轉換為幾何點。

??ST_Distance_Sphere(geom, ST_PointFromText(CONCAT('POINT(', 120.15, ' ', 30.28, ')')))?計算每個點與目標點之間的距離(單位為米)。

??ORDER BY distance?按距離從小到大排序

SELECT id, name, lng, lat,ST_Distance_Sphere(geom, ST_PointFromText(CONCAT('POINT(', 120.15, ' ', 30.28, ')'))) AS distance
FROM sys_district
ORDER BY distance
LIMIT 3;

? ? ? ? 3、其他方式

? ? ? ? 如果帶查詢的數據項不變化,類似于行政區劃的坐標,還可以把這些數據加載到內存中進行計算。

? ? ? ? 3.1 Java-使用 Haversine 公式來計算(不依賴三方庫)

????????創建表示位置的類

public class Location {private double lon;private double lat;public Location(double lon, double double lat) {this.lon = lon;this.lat = lat;}// Getter 和 Setter 方法}

????????使用 Haversine 公式計算兩點間的距離

public class DistanceCalculator {private static final int EARTH_RADIUS = 6371; // 地球半徑,單位為公里/*** 計算兩個經緯度點之間的距離*/public static double calculateDistance(Location loc1, Location loc2) {double lat1 = Math.toRadians(loc1.getLat());double lon1 = Math.toRadians(loc1.getLon());double lat2 = Math.toRadians(loc2.getLat());double lon2 = Math.toRadians(loc2.getLon());double dlat = lat2 - lat1;double dlon = lon2 - lon1;double a = Math.sin(dlat / 2) * Math.sin(dlat / 2) +Math.cos(lat1) * Math.cos(lat2) *Math.sin(dlon / 2) * Math.sin(dlon / 2);double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));return EARTH_RADIUS * c; // 返回單位為公里}
}

????????查找最近的數據點

public class NearestLocationFinder {public static LocationData findNearestLocation(List<LocationData> locations, Location targetLocation) {LocationData nearest = null;double minDistance = Double.MAX_VALUE;for (LocationData location : locations) {Location currentLocation = new Location(location.getLocation().getLon(), location.getLocation().getLat());double distance = DistanceCalculator.calculateDistance(currentLocation, targetLocation);if (distance < minDistance) {minDistance = distance;nearest = location;}}return nearest;}
}

? ? ? ? 調用方法

public class Main {public static void main(String[] args) {// 已加載所有的位置數據List<LocationData> locations = loadData();// 輸入的經緯度Location targetLocation = new Location(115.65, 34.43);// 查找最近的位置LocationData nearest = NearestLocationFinder.findNearestLocation(locations, targetLocation);System.out.println("最近的位置是: " + nearest.getName());}// 加載數據private static List<LocationData> loadData() {return new ArrayList<>();}
}

? ? ? ? 4、Java-使用JTS STRtree(依賴三方庫)

? ? ? ? maven依賴

<dependency><groupId>org.locationtech.jts</groupId><artifactId>jts-core</artifactId><version>1.18.2</version>
</dependency>

?????????調用方法

public class NearestPointFinder {public static void main(String[] args) {// 創建一個包含所有位置信息的列表List<LocationData> locations = loadData();// 輸入的經緯度double lon = 115.65, lat = 34.43;// 使用JTS的STRtree加速查詢STRtree tree = new STRtree();GeometryFactory geometryFactory = new GeometryFactory();for (LocationData location : locations) {Point point = geometryFactory.createPoint(new Coordinate(location.getLocation().getLon(), location.getLocation().getLat()));tree.insert(point.getEnvelopeInternal(), location);}Point targetPoint = geometryFactory.createPoint(new Coordinate(lon, lat));LocationData nearest = (LocationData) tree.nearestNeighbour(targetPoint.getEnvelopeInternal(), null);System.out.println("最近的位置是: " + nearest.getName());}private static List<LocationData> loadData() {// 加載位置數據return new ArrayList<>();}
}

? ? ? ? 還有其他的一些三方庫:H3 by Uber、GeoTools、Spatial4j等。

總結:沒有最好的,只有最適合的,按需設計。

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

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

相關文章

Appium等待機制--強制等待、隱式等待、顯式等待

書接上回&#xff0c;Appium高級操作--其他操作-CSDN博客文章瀏覽閱讀182次&#xff0c;點贊6次&#xff0c;收藏7次。書接上回Appium高級操作--從源碼角度解析--模擬復雜手勢操作-CSDN博客。https://blog.csdn.net/fantasy_4/article/details/146162851主要講解了Appium的一些…

【架構藝術】Go語言微服務monorepo的代碼架構設計

近期因為項目架構升級原因&#xff0c;筆者著手調研一些go項目monorepo的代碼架構設計&#xff0c;目標是長期把既有微服務項目重要的部分都轉移到monorepo上面&#xff0c;讓代碼更容易維護&#xff0c;協作開發更加方便。雖然經驗不多&#xff0c;但既然有了初步的調研&#…

深入解析 JVM —— 從基礎概念到實戰調優的全鏈路學習指南

文章目錄 一、為什么要學習 JVM&#xff1f;1. 面試必備與技能提升2. 性能優化與問題診斷3. 編寫高質量代碼 二、JVM 基礎概念與體系結構1. JVM 簡介2. JDK、JRE 與 JVM 三、JVM 內存模型1. 線程私有區2. 線程共享區 四、類加載機制與雙親委派1. 類加載過程2. 雙親委派模型3. 動…

前端及后端實現csv文件下載功能

方法一、 前端內容&#xff1a; const url window.URL.createObjectURL(new Blob([res.data])); const link document.createElement(a); link.href url; const fileNameDateTime getFormattedDateTime(); const filename "用戶提現列表"fileNameDateTime.csv…

QT中委托QStyledItemDelegate的使用

目錄 一、子類化委托 二、委托方法實現 1)createEditor 2)setEditorData 3)setModelData 4)updateEditorGeometry 三、委托使用 四、總結 Qt的數據容器控件采用模型/視圖(model/view)架構設計。模型用于存放控件的數據,視圖則用于顯示編輯數據,而委托則是…

OpenCV實現視頻背景提取

在計算機視覺領域&#xff0c;背景減除&#xff08;Background Subtraction&#xff09;是一種常用的技術&#xff0c;用于從視頻序列中提取前景對象。 背景減除的核心思想是通過建模背景&#xff0c;然后將當前幀與背景模型進行比較&#xff0c;從而分離出前景對象。 OpenCV…

NFS實驗配置筆記

NFS NFS服務 nfs&#xff0c;最早是Sun這家公司所發展出來的&#xff0c;它最大的功能就是可以透過網絡&#xff0c;讓不同的機器&#xff0c;不同的操作系統&#xff0c;進行實現文檔的共享。所以你可以簡單的將他看做是文件服務器。 實驗準備 ①先準備一個服務器端的操作…

C語言【數據結構】:理解什么是數據結構和算法(啟航)

引言 啟航篇&#xff0c;理解什么是數據結構和算法 在 C 語言編程領域&#xff0c;數據結構和算法是兩個核心且緊密相關的概念 一、數據結構 定義 數據結構是指相互之間存在一種或多種特定關系的數據元素的集合&#xff08;比如數組&#xff09;&#xff0c;它是組織和存儲數…

Vue.js 3 的設計思路:從聲明式UI到高效渲染機制

目錄 一、聲明式UI與虛擬DOM的靈活性 二、渲染器&#xff1a;虛擬DOM到真實DOM的橋梁 三、組件的本質與實現 四、編譯與運行時的協同優化 五、性能與可維護性的權衡 總結 Vue.js 3 作為新一代前端框架&#xff0c;其設計理念在聲明式UI描述、虛擬DOM優化、組件化架構…

深度學習|MAE技術全景圖:自監督學習的“掩碼魔法“如何重塑AI基礎

一、引言&#xff1a;深度學習的困境與自監督的曙光 深度學習&#xff08;Deep Learning&#xff09;無疑是當今人工智能領域基礎中的基礎。從圖像識別到自然語言處理&#xff08;NLP&#xff09;&#xff0c;它在無數任務中展現了卓越性能。例如&#xff0c;在安防監控中&…

深度學習正則化技術之權重衰減法、暫退法(通俗易懂版)

一、影響模型泛性的因素有&#xff1f;什么是正則化技術&#xff1f;有什么用&#xff1f; 通常&#xff0c;影響模型泛化能力的因素有&#xff1a; 可調節參數的個數&#xff1a;可調節的參數過少&#xff0c;會造成模型過于簡單&#xff0c;欠擬合&#xff1b;過多&#xf…

爬蟲逆向:Unicorn 詳細使用指南

文章目錄 1. Unicorn 介紹1.1 Unicorn 的特點1.2 Unicorn功能2. 安裝 Unicorn2.1 安裝 Python 綁定2.2 安裝 Unicorn 核心庫3. Unicorn 的基本使用3.1 初始化模擬器3.2 映射內存3.3 寫入代碼3.4 設置寄存器3.5 執行代碼3.6 讀取寄存器4. Unicorn 的高級功能4.1 鉤子函數4.2 異常…

【SpringBoot】實現登錄功能

在上一篇博客中&#xff0c;我們講解了注冊頁面的實現。在此基礎上會跳轉到登錄頁面&#xff0c;今天給大家帶來的是使用 SpringBoot&#xff0c;MyBatis&#xff0c;Html&#xff0c;CSS&#xff0c;JavaScript&#xff0c;前后端交互實現一個登錄功能。 目錄 一、效果 二、…

【小白向】Ubuntu|VMware 新建虛擬機后打開 SSH 服務、在主機上安裝vscode并連接、配置 git 的 ssh

常常有人問VMware-Tools裝了也復制粘貼不了怎么辦&#xff0c;這個東西影響因素太多了&#xff0c;具體解決辦法你們可以參考一下&#xff1a;【經驗】VMware&#xff5c;虛擬機只能使用鼠標無法使用鍵盤、裝不了或裝了VMware-Tools無法復制粘貼的可能解決辦法_增強型鍵盤驅動程…

mingw工具源碼編譯

ming-w64 mingw編譯生成的庫&#xff0c;需要mingw的lib文件支持。 https://github.com/mingw-w64/mingw-w64 使用msys2的bash git checkout v8.0.3 ./configure --disable-dependency-tracking --targetx86_64-w64-mingw32 mingw32-make.exe -j4 修改makefile中的make 改成mi…

LSTM方法實踐——基于LSTM的汽車銷量時序建模與預測分析

Hi&#xff0c;大家好&#xff0c;我是半畝花海。本實驗基于汽車銷量時序數據&#xff0c;使用LSTM網絡&#xff08;長短期記憶網絡&#xff09;構建時間序列預測模型。通過數據預處理、模型訓練與評估等完整流程&#xff0c;驗證LSTM在短期時序預測中的有效性。 目錄 一、實驗…

Stable Diffusion教程|快速入門SD繪畫原理與安裝

什么是Stable Diffusion&#xff0c;什么是煉丹師&#xff1f;根據市場研究機構預測&#xff0c;到2025年全球AI繪畫市場規模將達到100億美元&#xff0c;其中Stable Diffusion&#xff08;簡稱SD&#xff09;作為一種先進的圖像生成技術之一&#xff0c;市場份額也在不斷增長&…

Webpack構建流程詳解優化前端性能\Dev-Server與Proxy\網絡攻擊\HMR

簡版 核心流程圖 根據&#xff0c;Webpack的構建流程分為初始化、編譯和輸出三個階段。初始化階段讀取配置、加載插件、實例化Compiler。編譯階段&#xff08;構建依賴關系&#xff09;涉及Compiler類的運行&#xff0c;生成Compilation對象&#xff0c;處理模塊依賴。輸出階…

《Transformer如何進行圖像分類:從新手到入門》

引言 如果你對人工智能&#xff08;AI&#xff09;或深度學習&#xff08;Deep Learning&#xff09;感興趣&#xff0c;可能聽說過“Transformer”這個詞。它最初在自然語言處理&#xff08;NLP&#xff09;領域大放異彩&#xff0c;比如在翻譯、聊天機器人和文本生成中表現出…

Java --- 根據身份證號計算年齡

介紹 根據身份證號計算年齡 Java代碼 /*** 根據身份證號計算年齡* param birthDateStr* return*/public static int calculateAge(String birthDateStr) {try {birthDateStrbirthDateStr.substring(6,68);// 定義日期格式SimpleDateFormat sdf new SimpleDateFormat("…