MongoDB06 - MongoDB 地理空間

MongoDB06 - MongoDB 地理空間

文章目錄

  • MongoDB06 - MongoDB 地理空間
    • 一:地理空間數據基礎
      • 1:地理數據表示方式
        • 1.1:GeoJSON 格式
        • 1.2:傳統坐標對
      • 2:地理空間索引
        • 2.1:2dsphere 索引
        • 2.2:2d索引
        • 2.3:混合索引
    • 二:地理空間查詢和聚合
      • 1:完全包含于幾何圖形
      • 2:與指定幾何圖形相交
      • 3:找附近點并按距離排序
      • 4:地理空間的聚合操作
      • 5:地理空間計算函數
    • 三:實際應用示例
      • 1:附近地點搜索
      • 2:地理圍欄檢查
      • 3:多點距離計算
    • 四:Spring Boot Data整合
      • 1:依賴和配置
      • 2:數據模型定義
      • 3:Repository 層
      • 4:服務Service層
      • 5:控制Controller層

一:地理空間數據基礎

1:地理數據表示方式

MongoDB 支持兩種主要的地理空間數據表示方式: GeoJSON 格式 & 傳統坐標對[經度,緯度]

  • 經度在前:GeoJSON 規定坐標順序為 [經度, 緯度]
  • 有效范圍:經度:-180 到 180 & 緯度:-90 到 90
1.1:GeoJSON 格式

GeoJSON支持如下的類型:

Point - 點

{ type: "Point", coordinates: [longitude, latitude] 
}

LineString - 線

{ type: "LineString", coordinates: [[lon1,lat1], [lon2,lat2], ...] 
}

Polygon - 多邊形(閉合環)

{ type: "Polygon", coordinates: [[[lon1,lat1], [lon2,lat2], ..., [lon1,lat1]] // 外環// 可以有多個內環(洞)
]}

還有一些不太常用的:MultiPoint、MultiLineString、MultiPolygon、GeometryCollection

1.2:傳統坐標對

簡單數組格式:[longitude, latitude] -> 僅適用于 2d 索引,不支持復雜幾何形狀

{loc: [longitude, latitude]
}

2:地理空間索引

2.1:2dsphere 索引

地球球面幾何計算,支持所有的 GeoJSON 類型,計算球面距離

支持 $nearSphere、$geoWithin、$geoIntersects 等操作

db.collection.createIndex({ <locationField>: "2dsphere" } // 創建索引
)
2.2:2d索引

平面幾何計算,僅支持點數據(坐標對),計算平面距離(不考慮地球曲率)。·性能更高但精度較低

db.collection.createIndex({ <locationField>: "2d" }
)
2.3:混合索引

可以組合地理空間索引與其他字段:

db.places.createIndex({ location: "2dsphere", name: 1 }
)

二:地理空間查詢和聚合

1:完全包含于幾何圖形

$geoWithin -> 查找完全包含在指定幾何圖形內的文檔

  • 使用 GeoJSON:$geometry
  • 使用傳統坐標:$box$polygon$center$centerSphere
db.places.find({location: {$geoWithin: {// 返回在如下多邊形中的文檔$geometry: {type: "Polygon",coordinates: [[ [0,0], [3,6], [6,1], [0,0] ]}}}
})

2:與指定幾何圖形相交

$geoIntersects -> 查找與指定幾何圖形相交的文檔

db.places.find({location: {$geoIntersects: {// 返回和這條線相交的文檔$geometry: {type: "LineString",coordinates: [[0,0], [5,5]]}}}
})

3:找附近點并按距離排序

$near -> 找附近點并按距離排序

db.places.find({location: {$near: {// 找到舉例給定中心點附近的點,最小距離100m,最大距離500m$geometry: {type: "Point",coordinates: [-73.9667, 40.78]},$maxDistance: 500,  // 米(2dsphere)$minDistance: 100}}
})

4:地理空間的聚合操作

使用$geoNear是基于距離的管道聚合,對于$geoNear有如下的說明:

  • 必須是管道的第一階段
  • 自動按距離排序
  • 可返回計算的距離值
db.places.aggregate([{$geoNear: {// near:參考點// distanceField:存儲距離的字段// maxDistance/minDistance:距離范圍// spherical:是否使用球面計算// query:附加查詢條件// $geoWithin 可在聚合中使用// 結合 $project 計算自定義地理空間數據near: { type: "Point", coordinates: [-73.9667, 40.78] },distanceField: "distance",maxDistance: 2000,spherical: true,query: { category: "Park" }}}
])

5:地理空間計算函數

$geoDistance:計算兩點間距離

{$project: {distance: {$geoDistance: {// 起點是文檔中的location字段start: "$location",// 終點是GeoJson的坐標點end: { type: "Point", coordinates: [-73.98, 40.77] },distanceMultiplier: 0.001 // 轉換為公里}}}
}

三:實際應用示例

1:附近地點搜索

db.places.find({location: {$nearSphere: {// 在給定點1km之內的文檔$geometry: {type: "Point",coordinates: [currentLng, currentLat]},$maxDistance: 1000 // 1公里內}},category: "restaurant"
}).limit(20)

2:地理圍欄檢查

// 檢查點是否在配送區域內
db.deliveryZones.find({area: {$geoIntersects: {$geometry: {type: "Point",coordinates: [orderLng, orderLat]}}}
})

3:多點距離計算

db.stores.aggregate([{$geoNear: {// 指定參考點near: { type: "Point", coordinates: [userLng, userLat] },// 指定輸出字段名,用于存儲計算的距離值distanceField: "distance",// 使用球面spherical: true}},// 結果過濾,只要5km內的{ $match: { distance: { $lte: 5000 } } }, // 5公里內// 按照距離正序排序{ $sort: { distance: 1 } }
])

四:Spring Boot Data整合

1:依賴和配置

<dependencies><!-- Spring Boot Starter Data MongoDB --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId></dependency><!-- 其他必要依賴 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Lombok (可選) --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency>
</dependencies>
# application.properties
spring:data:mongodb:host: localhostport: 27017database: geo_db

2:數據模型定義

創建地理空間實體

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import org.springframework.data.mongodb.core.mapping.Document;
import lombok.Data;@Data
@Document(collection = "places")
public class Place {@Idprivate String id;private String name;private String category;private GeoJsonPoint location;  // 使用GeoJsonPoint存儲地理坐標// 構造方法、getter/setter等// Lombok的@Data注解會自動生成這些
}

地理空間索引配置

import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.index.GeoSpatialIndexType;
import org.springframework.data.mongodb.core.index.GeoSpatialIndexed;
import org.springframework.data.mongodb.core.index.IndexDefinition;
import org.springframework.data.mongodb.core.index.IndexOperations;
import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener;
import org.springframework.data.mongodb.core.mapping.event.BeforeConvertEvent;@Configuration
public class MongoConfig {// 添加監聽器@Beanpublic BeforeConvertListener beforeConvertListener() {return new BeforeConvertListener();}// 定義監聽器,繼承地理事件監聽器public static class BeforeConvertListener extends AbstractMongoEventListener<Place> {@Overridepublic void onBeforeConvert(BeforeConvertEvent<Place> event) {// 說明要進行索引操作了IndexOperations indexOps = event.getCollection().getIndexOperations();// 定義索引// 確保location字段有2dsphere索引IndexDefinition indexDef = new GeoSpatialIndexDefinition("location").typed(GeoSpatialIndexType.GEO_2DSPHERE);// 添加索引indexOps.ensureIndex(indexDef);}}
}

3:Repository 層

import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.Point;
import org.springframework.data.mongodb.repository.Query;
import java.util.List;public interface PlaceRepository extends MongoRepository<Place, String> {// 查找附近的點(按距離排序)List<Place> findByLocationNear(Point point, Distance distance);// 查找指定類別附近的點List<Place> findByCategoryAndLocationNear(String category, Point point, Distance distance);// 使用GeoJSON多邊形查詢@Query("{ 'location' : { $geoWithin : { $geometry : { type : 'Polygon', coordinates : ?0 } } }")List<Place> findWithinPolygon(List<List<Double[]>> polygonCoordinates);// 查找與指定線相交的地點@Query("{ 'location' : { $geoIntersects : { $geometry : { type : 'LineString', coordinates : ?0 } } }")List<Place> findIntersectingLine(List<Double[]> lineCoordinates);// 如果是聚合查詢@Aggregation(pipeline = {"{ $geoNear: { " +"  near: { type: 'Point', coordinates: [ ?0, ?1 ] }, " +"  distanceField: 'distance', " +"  maxDistance: ?2, " +"  spherical: true " +"} }","{ $match: { category: ?3 } }","{ $sort: { distance: 1 } }","{ $limit: ?4 }"})List<Place> findNearbyPlacesWithAggregation(double longitude, double latitude, double maxDistanceInMeters,String category,int limit);
}

4:服務Service層

import org.springframework.data.geo.Distance;
import org.springframework.data.geo.Metrics;
import org.springframework.data.geo.Point;
import org.springframework.stereotype.Service;
import java.util.List;@Service
public class GeoService {private final PlaceRepository placeRepository;public GeoService(PlaceRepository placeRepository) {this.placeRepository = placeRepository;}/*** 查找附近的地點* @param longitude 經度* @param latitude 緯度* @param distance 距離(公里)* @return 附近的地點列表*/public List<Place> findNearbyPlaces(double longitude, double latitude, double distance) {Point point = new Point(longitude, latitude);Distance radius = new Distance(distance, Metrics.KILOMETERS);return placeRepository.findByLocationNear(point, radius);}/*** 查找特定類別附近的地點*/public List<Place> findNearbyPlacesByCategory(double longitude, double latitude, double distance, String category) {Point point = new Point(longitude, latitude);Distance radius = new Distance(distance, Metrics.KILOMETERS);return placeRepository.findByCategoryAndLocationNear(category, point, radius);}/*** 多邊形區域查詢*/public List<Place> findWithinPolygon(List<List<Double[]>> polygonCoordinates) {return placeRepository.findWithinPolygon(polygonCoordinates);}/*** 與線相交的地點查詢*/public List<Place> findIntersectingLine(List<Double[]> lineCoordinates) {return placeRepository.findIntersectingLine(lineCoordinates);}// 使用 GeoJson 對象public List<Place> findWithinGeoJsonPolygon(GeoJsonPolygon polygon) {return mongoTemplate.find(Query.query(Criteria.where("location").within(polygon)), Place.class);
}

5:控制Controller層

import org.springframework.web.bind.annotation.*;
import org.springframework.data.geo.Point;
import java.util.List;@RestController
@RequestMapping("/api/places")
public class PlaceController {private final GeoService geoService;public PlaceController(GeoService geoService) {this.geoService = geoService;}@GetMapping("/nearby")public List<Place> getNearbyPlaces(@RequestParam double longitude,@RequestParam double latitude,@RequestParam(defaultValue = "5") double distance) {return geoService.findNearbyPlaces(longitude, latitude, distance);}@GetMapping("/nearby/{category}")public List<Place> getNearbyPlacesByCategory(@PathVariable String category,@RequestParam double longitude,@RequestParam double latitude,@RequestParam(defaultValue = "5") double distance) {return geoService.findNearbyPlacesByCategory(longitude, latitude, distance, category);}@PostMapping("/within-polygon")public List<Place> getPlacesWithinPolygon(@RequestBody List<List<Double[]>> polygonCoordinates) {return geoService.findWithinPolygon(polygonCoordinates);}@PostMapping("/intersecting-line")public List<Place> getPlacesIntersectingLine(@RequestBody List<Double[]> lineCoordinates) {return geoService.findIntersectingLine(lineCoordinates);}
}

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

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

相關文章

Bugku——WEB篇(持續更新ing)

目錄 一、滑稽 二、計算器 方法一 方法二 三、alert 四、你必須讓他停下 五、頭等艙 六、GET 七、POST 方法一 方法二 八、source 九、矛盾 十、備份是個好習慣 一、滑稽 1.啟動環境后&#xff0c;訪問URL&#xff0c;頁面出現了一堆滑稽表情 2.按f12(或fnf12)打…

Linux 網絡命名空間的奧秘:深入解析struct net與內核模塊編譯陷阱

引言:網絡隔離的基石 在Linux容器化技術(如Docker)和云計算網絡中,網絡命名空間是實現網絡隔離的核心機制。每個隔離的網絡環境都由一個關鍵的內核數據結構描述——struct net。這個結構體不僅是網絡隔離的技術基礎,也是內核開發者常遇到的編譯陷阱源頭。 一、解剖網絡命…

idea的EasyCode插件連接瀚高數據庫(APP)

文章目錄 環境癥狀問題原因解決方案 環境 系統平臺&#xff1a;Linux x86-64 Red Hat Enterprise Linux 7 版本&#xff1a;5.6.5 癥狀 客戶在idea工具中使用EasyCode插件連接瀚高數據庫的企業版時&#xff0c;連接設置的url中提示“jdbc:highgo不存在”的錯誤 問題原因 E…

VMware設置虛擬機為固定IP

1. 修改虛擬網絡編輯器 打開虛擬機網絡“編輯” 點擊“VMnet8” 選擇“NAT”模式 修改網關&#xff1a;前面的不要修改&#xff0c;最后一位設置為“1”&#xff0c;然后確定 記住這里的網關&#xff0c;后面的配置要保持一致 設置子網IP和子網掩碼&#xff1a;一般就…

智核引擎融合生成式AI,重塑企業知識圖譜與研發創新范式!

目錄 系統架構設計核心實現步驟步驟1&#xff1a;知識圖譜構建與數據預處理步驟2&#xff1a;生成式AI與知識圖譜融合&#xff08;RAG增強&#xff09;步驟3&#xff1a;智能推理工作流 核心流程可視化企業級部署方案性能優化策略應用場景示例結語 本文將手把手實現企業級知識圖…

LogisticRegression(solver = ‘lbfgs‘)的ConvergenceWarning問題解決

&#x1f466;&#x1f466;一個帥氣的boy&#xff0c;你可以叫我Love And Program &#x1f5b1; ?個人主頁&#xff1a;Love And Program的個人主頁 &#x1f496;&#x1f496;如果對你有幫助的話希望三連&#x1f4a8;&#x1f4a8;支持一下博主 LogisticRegression的Co…

web3 docs

區塊鏈重構信任機制&#xff0c;去中心化&#xff0c;用唯一的hash編號來實現防篡改。以數字貨幣的形式交易&#xff0c;個人持有唯一的數字秘鑰(唯一&#xff0c;不可篡改) 詳見 以太坊的白皮書 和 數字貨幣 (加密貨幣實現隱私交易) 底層基礎的很多特點 1.例如p2p&#xf…

AI入門 | 計算自注意力時QK^T的計算復雜度是多少?

0. 背景 假設我們有兩個矩陣&#xff1a; 矩陣 A&#xff0c;尺寸為 (n, d_k)矩陣 B&#xff0c;尺寸為 (d_k, n) 我們要計算它們的乘積 C A * B。 那么這個過程所需的計算量是多少&#xff1f; 1. 結果矩陣的尺寸 首先&#xff0c;結果矩陣 C 的尺寸是由第一個矩陣的行數…

NeRF-Lidar實景重建:大疆Mavic 4 Pro低成本建模方案(2025實戰指南)

摘要 面對傳統激光雷達建模??成本高昂??&#xff08;單設備超$20萬&#xff09;與??操作復雜??的行業痛點&#xff0c;本文提出基于消費級無人機大疆Mavic 4 Pro的??NeRF-LiDAR融合重建方案??&#xff0c;實現厘米級精度建模成本降低至1/10。核心技術突破在于&…

x64dbg設置條件斷點

提示:文章寫完后,目錄可以自動生成,如何生成可參考右邊的幫助文檔 文章目錄 前言一、x64是什么?二、條件斷點1.CreateWindowExW函數設置當窗口名稱為xxx字符串時候break總結前言 提示:這里可以添加本文要記錄的大概內容: x64dbg設置條件斷點 版本 2024 mar 27 提示:以…

RNN人名分類器案例

RNN人名分類器案例 1 任務目的&#xff1a; 目的: 給定一個人名&#xff0c;來判定這個人名屬于哪個國家 典型的文本分類任務: 18分類---多分類任務 2 數據格式 注意&#xff1a;兩列數據&#xff0c;第一列是人名&#xff0c;第二列是國家類別&#xff0c;中間用制表符號&q…

鴻蒙HarmonyOS 關于圖片、視頻的選擇詳解

背景 在聊天軟件中&#xff0c;發送相冊中視頻和照片、用相機拍攝視頻和圖片發送是很常用的功能。在Android和iOS端&#xff0c;大部分應用都通過API方式定義UI來實現相冊選擇照片、視頻&#xff0c;相機拍攝照片、視頻&#xff0c;它們一般都支持以下功能&#xff1a; 相冊選…

iOS 網絡請求斷連重試失敗?抓包分析丟包原因的完整流程

在移動 App 的開發中&#xff0c;中斷網絡環境&#xff08;如切換到飛行模式再回網&#xff09;后&#xff0c;App 在重連過程中有時會出現請求未重新發送或丟包的情況。這類問題難重現、難定位&#xff0c;尤其在 iOS 平臺上更容易被忽視。我們最近就遇到一個用戶反饋“切換網…

使用 DHTMLX Gantt 添加迷你地圖:提升大型項目可視化與導航體驗

在應對數千個任務構成的大型項目時&#xff0c;DHTMLX Gantt 以其卓越的性能表現和流暢渲染能力廣受歡迎。然而&#xff0c;在實際使用中&#xff0c;終端用戶往往需要快速定位到時間線中的特定位置&#xff0c;這在面對龐雜任務結構時尤為困難。為此&#xff0c;DHTMLX 提供了…

ROM修改進階教程------用于自啟腳本來打開系統的一些常用開關等指令 備份收藏 【一】

在定制化rom中。有很多項目需要反編譯系統的相關應用來實現。但有些功能項完全可以使用指令來更改。那么結合自啟腳本就可以很方便的來實現很多功能。網絡雖然有很多類似的指令,但一些相關定制化項目的指令很少見而且不全面。此博文將全面收錄此類指令。方便rom修改用戶借鑒參…

騰訊云TSE注冊中心實戰:Nacos高可用集群搭建與流量治理避坑指南

1. 為什么選擇騰訊云TSE托管Nacos&#xff1f; 在微服務架構中&#xff0c;注冊中心承擔著服務發現與配置管理的核心職能。Nacos作為阿里開源的動態服務發現組件&#xff0c;已成為國內微服務生態的事實標準。騰訊云微服務引擎TSE&#xff08;Tencent Cloud Service Engine&am…

領域驅動設計(DDD)【26】之CQRS模式初探

文章目錄 一 CQRS初探&#xff1a;理解基本概念1.1 什么是CQRS&#xff1f;1.2 CQRS與CRUD的對比1.3 為什么需要CQRS&#xff1f; 二 CQRS深入&#xff1a;架構細節2.1 基本架構組成2.2 數據流示意圖 三 CQRS實戰&#xff1a;電商訂單案例3.1 傳統CRUD方式的訂單處理3.2 CQRS方…

項目測試-接口測試

軟件測試的分類 軟件測試主要分硬件和軟件 硬件測試: cpu,內存條,顯卡...測試可以看得見摸得著的東西 軟件測試: web,app,小程序... 測試可以看得見摸不著的東西 web端 web端是在電腦上常常使用的, 也可以稱之為網站.(web端是B/S架構) web端的客戶端是任何一個訪問這個網…

相機的光圈

光圈&#xff08;Aperture&#xff09;是鏡頭中一個控制光線進入相機的開口&#xff0c;它在攝影中起著至關重要的作用。光圈的大小決定了進入相機傳感器的光線數量&#xff0c;并影響曝光、景深、以及拍攝效果。光圈參數通常用f/值&#xff08;光圈值&#xff09;來表示&#…

HarmonyOS NEXT倉頡開發語言實戰案例:小而美的旅行App

大家周末好&#xff0c;本文分享一個小而美的旅行app首頁&#xff0c;效果圖如下&#xff1a; 很顯然這個頁面還是使用List容器&#xff0c;頁面兩側有統一的邊距&#xff0c;我們可以在List容器統一設置&#xff1a; List(space:20){ } .padding(left:14,right:14,top:62) .w…