o2o附近的商家功能常見的演算法:geohash和spatial4j調試實戰

2019年12月06日07:55:05 科技 1861

開篇

我調試了很多開源項目,包括開源商城、IM即時通訊等很多,感興趣的可以看看源碼點我頭像進去,覺得有用給個關注吧。

最近在看o2o相關的原理,網上說了很多geohash演算法的原理。但其實原理網上有很多,但真正的調試少之又少,今天就來寫代碼調試一下geo演算法和spatial4工具j。輕鬆實現,附近的商家功能。覺得有用,就點個贊轉個發吧。看文章的時候最好是跟著做,如果沒時間就收藏轉發吧。


o2o附近的商家功能常見的演算法:geohash和spatial4j調試實戰 - 天天要聞

geohash演算法原理簡單介紹

geo 是地理位置的geography 的縮寫,hash其實就是hash演算法。大家都知道,我們平常用的百度地圖,高德地圖其實每一個點都是有經緯度的。你可以理解為geohash,其實就是經緯度經過一些列運算出來的hash值,相似的經緯度得到的geohash值前綴幾乎一致,這樣就可以把一個區域內的點都可以直接在資料庫中查出來,當然具體原理自己可以去搜索。這裡就不介紹了,今天重點介紹,如何使用。

源碼可以到github上看:https://github.com/kungfoo/geohash-java


o2o附近的商家功能常見的演算法:geohash和spatial4j調試實戰 - 天天要聞

spatial4j工具

其實地球是球形的大家都知道,但基本上在地圖上你可以認為是平面。例如查詢附近1km的範圍你怎麼查呢?給定圓心坐標和半徑,求該圓外切正方形四個頂點的坐標。不是嗎?這個計算我們就用到spatial4j了。github上的地址是:https://github.com/locationtech/spatial4j


o2o附近的商家功能常見的演算法:geohash和spatial4j調試實戰 - 天天要聞

核心調試

1、建表,建工程

新建一個spring boot 工程,集成mybatis等,當然建個商戶表,有商戶名稱,經緯度,geohash等欄位。

CREATE TABLE `merchant` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增主鍵',
`merchant_name` VARCHAR(64) NOT NULL COMMENT '名稱',
`longitude` DOUBLE(9,6) NOT NULL COMMENT '經度',
`latitude` DOUBLE(8,6) NOT NULL COMMENT '緯度',
`geo_code` CHAR(12) NOT NULL COMMENT 'geohash編碼',
PRIMARY KEY (`id`),
KEY `idx_merchant_longitude_latitude` (`longitude`,`latitude`),
KEY `idx_merchant_geo_code` (`geo_code`)
)COMMENT='商戶表' CHARSET=utf8mb4 ENGINE=InnoDB;


o2o附近的商家功能常見的演算法:geohash和spatial4j調試實戰 - 天天要聞

2、方法一、查詢附近的1km的用spatial4j實現

A、首先引入jar包:

 <dependency>
<groupId>com.spatial4j</groupId>
<artifactId>spatial4j</artifactId>
<version>0.5</version>
</dependency>


o2o附近的商家功能常見的演算法:geohash和spatial4j調試實戰 - 天天要聞

B、計算四個點的的值

public static void main(String[] args) {
//起始點經緯度
double lon = 116.312528, lat = 39.983733;
// 千米
int radius = 1;
SpatialContext geo = SpatialContext.GEO;
Rectangle rectangle = geo.getDistCalc().calcBoxByDistFromPt(
geo.makePoint(lon, lat),
radius * DistanceUtils.KM_TO_DEG, geo, null);

System.out.println(rectangle.getMinX() +
"-" + rectangle.getMaxX());// 經度範圍
System.out.println(rectangle.getMinY() +
"-" + rectangle.getMaxY());// 緯度範圍
}


o2o附近的商家功能常見的演算法:geohash和spatial4j調試實戰 - 天天要聞

C、根據範圍,在資料庫中查找即可,查到附近1km的數據。當然,經緯度最好做聯合索引。這兩個數據是上面算出來的。

SELECT id, merchant_name
FROM merchant
WHERE (longitude BETWEEN ? AND ?) AND (latitude BETWEEN ? AND ?);

3、根據geohash查詢。此時會用到geo_code 欄位。

A、引入geohash的jar包

<!-- https://mvnrepository.com/artifact/ch.hsr/geohash -->
<dependency>
<groupId>ch.hsr</groupId>
<artifactId>geohash</artifactId>
<version>1.3.0</version>
</dependency>


o2o附近的商家功能常見的演算法:geohash和spatial4j調試實戰 - 天天要聞

B、對照geohash的長度對應範圍表,我們可以知道,查詢附近1km的數據,只要長度是5就可以了。具體計算,GeohashUtils.encodeLatLon(lat, lon, 5),代入底線sql即可。

SELECT id, merchant_name
FROM merchant
WHERE geo_code LIKE CONCAT(?, '%');

o2o附近的商家功能常見的演算法:geohash和spatial4j調試實戰 - 天天要聞

C、但geohash有邊界問題誤差。因為geohash是某個區域的共同的hash,索引邊界以外的距離很近的點可能造成geohash完全不同,那麼怎麼辦呢?其實也不難解決,你這個時候把周圍的八個區域的geohash都算出來即可。

public static void main(String[] args) {
// 移動設備經緯度
double lon = 116.312528, lat = 39.983733;
GeoHash geoHash = GeoHash.
withCharacterPrecision
(lat, lon, 6);
// 當前
System.out.println(geoHash.toBase32());
// N, NE, E, SE, S, SW, W, NW
System.out.println("---------------------------");
//東南西北,東北、西北、東南、西南等
GeoHash[] adjacent = geoHash.getAdjacent();
for (GeoHash hash : adjacent) {
System.out.println(hash.toBase32());
}
}

o2o附近的商家功能常見的演算法:geohash和spatial4j調試實戰 - 天天要聞


o2o附近的商家功能常見的演算法:geohash和spatial4j調試實戰 - 天天要聞

D、mysql查詢,查詢出這幾個區域的商家即可,geohash邊界問題就可以解決。

SELECT id, merchant_name
FROM merchant
WHERE geo_code IN (?, ?, ?, ?, ?, ?, ?, ?, ?);

結語

o2o中最常見的應用場景就是附近的商家,希望此篇文章對於o2o的同學有些幫助。覺得有用就點個贊轉發一下吧。

另外我還調試了其他很多開源項目

Java 開源的基於微服務 Spring cloud 快速開發腳手架調試實戰

超好用的 Java 開源 驗證碼 神器

Java 搭建的開源的spring boot商城系統實戰

前後端分離的開源在線考試系統調試實戰

調試個開源Java 輕量級高性能IM,單機支持幾十萬至百萬在線用戶

Java 百分之百開源 CMS 系統項目調試實戰

前端牛人寫的開源的CMS系統調試實戰,流體布局兼容手機端瀏覽器

覺得有用可以給個關注哦

科技分類資訊推薦

國家速滑館人形機器人實訓基地正式啟用 首批賽隊已入駐 - 天天要聞

國家速滑館人形機器人實訓基地正式啟用 首批賽隊已入駐

新華社北京7月6日電(記者陽娜)記者6日從北京市經濟和信息化局獲悉,國家速滑館人形機器人實訓基地近日正式啟用,首批8支隊伍進駐實訓基地,備戰2025世界人形機器人運動會。 5日,一場激烈的3V3機器人足球比賽在國家速滑館人形機器人實訓基地上演,由北京信息科技大學光熾隊對陣中國農業大學山海隊,這是實訓基地的第一場...
現在賺錢越來越難了?恰恰相反,做到這 3 點,不賺錢很難 - 天天要聞

現在賺錢越來越難了?恰恰相反,做到這 3 點,不賺錢很難

前幾天在小區便利店遇到鄰居陳姐,她一邊掃碼付包子錢一邊嘆氣:「現在錢太難賺了,我在超市幹了十年,工資才漲了兩千塊,連孩子補課費都快交不起了。」 回家路上刷到動態,做電商的 95 後小吳剛曬完訂單截圖,上個月凈利潤 18 萬,配文寫著:「其實
硬核出擊!Jeep與《侏羅紀世界》聯名款新車正式上市 - 天天要聞

硬核出擊!Jeep與《侏羅紀世界》聯名款新車正式上市

當硬核越野精神邂逅全球頂級IP,沉睡6500萬年的野性基因再度覺醒。2025年7月2日,Jeep圍繞電影《侏羅紀世界:重生》開啟跨界聯名合作,並發布兩款終極探索座駕——Jeep牧馬人侏羅紀世界探索版與Jeep角鬥士侏羅紀世界探索版。
十多年未解謎症,ChatGPT一語道破病因?微軟:「醫療超級智能」漸近 - 天天要聞

十多年未解謎症,ChatGPT一語道破病因?微軟:「醫療超級智能」漸近

《科創板日報》7月6日訊 十多年未解的疑難雜症,竟被AI一語道破病因?這個看似有些科幻的故事,來自一位網友在Reddit上分享的經歷,OpenAI總裁兼聯合創始人Greg Brockman也在今日轉發了這一事件。在這則Reddit帖子中,這位網友表示,十多年來自己一直被多種不明癥狀困擾。為此他做過脊椎核磁共振、CT 掃描、全套血液檢查(...
坐標北京,如何在體感40℃+的「桑拿天」保持優雅? - 天天要聞

坐標北京,如何在體感40℃+的「桑拿天」保持優雅?

最近咱們北京的天氣,可以說是「水深火熱」——早上出門像蒸桑拿,下午陣雨說來就來,晚上悶得睡不著覺。很多網友在後台留言「這天氣也太難熬了!」。高濕天氣連續多日達到90%以上的濕度,讓很多市民朋友高呼「難道回南天來了嗎?」今天,我們特意針對這個熱門話題,為大家詳細普及「回南天」和「桑拿天」的區別,還會教您...