- LBS-查找附近的人-地理坐標(biāo)定位詳解
- LBS-查找附近的人-MySQL實現(xiàn)
- LBS-查找附近的人-redis命令實現(xiàn)
- LBS-查找附近的人-redis-spring實現(xiàn)
接下來我們開始介紹mongodb的解決方案蚕键。mongodb也是早些年“快的”的解決方案你画。
地理空間數(shù)據(jù)
在MongoDB中沟娱,可以將地理空間數(shù)據(jù)存儲為 GeoJSON對象 或 傳統(tǒng)坐標(biāo)對 械巡。
GeoJSON對象
要計算類球體上的幾何體七婴,位置數(shù)據(jù)應(yīng)存儲為GeoJSON對象乳怎。
要指定GeoJSON數(shù)據(jù)彩郊,請使用嵌入式文檔:
- type:指定GeoJSON對象類型
- coordinates:指定對象的坐標(biāo)。
<field>: { type: <GeoJSON type> , coordinates: <coordinates> }
如:
location: {
type: "Point",
coordinates: [-73.856077, 40.848447]
}
GeoJSON對象在MongoDB地理空間查詢在球體上計算蚪缀,使用WGS84參考系統(tǒng)對GeoJSON對象進(jìn)行地理空間查詢秫逝。
傳統(tǒng)坐標(biāo)對
要計算歐幾里得平面上的距離,位置數(shù)據(jù)應(yīng)存儲為傳統(tǒng)坐標(biāo)對询枚,并使用2d索引违帆。將數(shù)據(jù)轉(zhuǎn)換為GeoJSON Point類型后,并通過2dsphere索引后傳統(tǒng)坐標(biāo)對也支持球面曲面計算金蜀。
要將數(shù)據(jù)指定為傳統(tǒng)坐標(biāo)對刷后,也有兩種數(shù)據(jù)格式可以使用,數(shù)組 或 嵌入式文檔 渊抄。 官方推薦首先使用 數(shù)組尝胆。
數(shù)組方式(首選):
<field>:[<longitude>, <latitude>]
嵌入式文檔方式:
<field>:{<field1>:<longitude>, <field2>:<latitude>}
- 有效經(jīng)度值介于-180和180。
- 有效的緯度值介于-90和90护桦。
注意:為什么要說這個經(jīng)緯度的有效值呢含衔,因為mongodb不僅僅是對地球的經(jīng)緯系統(tǒng)支持,也支持其他的平面坐標(biāo)系。如果使用緯度和經(jīng)度坐標(biāo)必須使用 longitude(經(jīng)度)在前贪染,latitude(緯度)在后的順序缓呛。
地理空間索引
在MongoDB中,地理數(shù)據(jù)相關(guān)的索引有兩種 2dsphere 和 2d杭隙。地球狀球體計算幾何的查詢應(yīng)使用 2dsphere 索引哟绊。 2d 索引在二維平面上使用存儲為點(diǎn)的數(shù)據(jù)的索引。該 2d 索引適用于MongoDB 2.2及更早版本中使用的傳統(tǒng)坐標(biāo)對寺渗。
當(dāng)然通過將數(shù)據(jù)轉(zhuǎn)換為GeoJSON Point類型匿情,MongoDB通過2dsphere索引支持傳統(tǒng)坐標(biāo)對上的球面曲面計算。所以 GeoJSON對象 比 傳統(tǒng)坐標(biāo)對 更加強(qiáng)大復(fù)雜信殊,但是 傳統(tǒng)坐標(biāo)對 也是支持 2dsphere
兩種索引的方式雖然不同炬称,不過,只要坐標(biāo)跨度不太大(比如幾百幾千公里)涡拘,這兩個索引計算出的距離相差幾乎可以忽略不計玲躯。
- 2dsphere
2dsphere索引支持在地球球上計算幾何的查詢。
db.collection.createIndex({ <location field>: "2dsphere" })
- 2d
2d索引支持在二維平面上計算幾何的查詢 鳄乏。盡管索引可以支持 $nearSphere 在球體上計算的查詢跷车,但如果可能的話,請使用 2dsphere 索引進(jìn)行球形查詢橱野。
db.collection.createIndex({ <location field> : "2d" })
其中 <location field> 的值是 GeoJSON對象 或 傳統(tǒng)坐標(biāo)對 的字段朽缴。
地理空間查詢運(yùn)算符
MongoDB提供了以下地理空間查詢操作符:
名稱 | 描述 |
---|---|
$geoIntersects | 選擇與GeoJSON幾何體相交的幾何體,2dsphere索引支持 |
$geoWithin | 選擇邊界GeoJSON幾何內(nèi)的幾何水援,2dsphere和2D索引支持 |
$near | 返回靠近點(diǎn)的地理空間對象密强。需要一個地理空間索引,2dsphere和2d索引支持 |
$nearSphere | 返回球體上某個點(diǎn)附近的地理空間物體蜗元。需要一個地理空間索引或渤,dsphere和2d索引支持 |
其中 $geoNear 包含 $match,$sort和$limit參數(shù)奕扣。輸出文件包含一個額外的距離字段薪鹦,并可包含位置標(biāo)識符字段。
下表列出了每個地理空間操作使用的地理空間查詢運(yùn)算符:
方法 | 坐標(biāo) | 說明 |
---|---|---|
$near(GeoJSON質(zhì)心點(diǎn)在這一行和下面一行惯豆,2dsphere) | 球形 | 另請參閱$nearSphere運(yùn)算符池磁,它在與GeoJSON和2dsphere索引一起使用時提供相同的功能。 |
$near(傳統(tǒng)坐標(biāo)楷兽,2d) | 平面 | |
$nearSphere(GeoJSON框仔,2dsphere) | 球形 | 提供與$near使用GeoJSON和2dsphere相同的功能。對于球形查詢拄养,最好使用 $nearSphere明確指定名稱中的球形查詢而不是$near |
$nearSphere(傳統(tǒng)坐標(biāo)离斩,2d) | 球形 | 改為使用GeoJSON點(diǎn)银舱。 |
$geoWithin:{ $geometry:...} | 球形 | |
$geoWithin:{ $box:...} | 平面 | |
$geoWithin:{ $polygon:...} | 平面 | |
$geoWithin:{ $center:...} | 平面 | |
$geoWithin:{ $centerSphere:...} | 球形 | |
$geoIntersects | 球形 | |
$geoNear(2dsphere) | 球形 | |
$geoNear(2d) | 平面 |
示例
GeoJSON對象數(shù)據(jù)
創(chuàng)建集合-插入數(shù)據(jù)-建立索引
#創(chuàng)建集合
db.createCollection("places")
#插入數(shù)據(jù)
db.places.insert({
name: "Central Park",
location: { type: "Point", coordinates: [ -73.97, 40.77 ] },
category: "Parks"
} );
db.places.insert({
name: "Sara D. Roosevelt Park",
location: { type: "Point", coordinates: [ -73.9928, 40.7193 ] },
category: "Parks"
} );
db.places.insert({
name: "Polo Grounds",
location: { type: "Point", coordinates: [ -73.9375, 40.8303 ] },
category: "Stadiums"
} );
#在location字段上創(chuàng)建索引
db.places.createIndex( { location: "2dsphere" } )
以下查詢使用$near操作返回距離指定GeoJSON至少1000米且最遠(yuǎn)5000米的數(shù)據(jù),并按從最近到最遠(yuǎn)的順序排序:
db.places.find(
{
location:
{ $near:
{
$geometry: { type: "Point", coordinates: [ -73.9667, 40.78 ] },
$minDistance: 1000,
$maxDistance: 5000
}
}
}
)
以下查詢使用$geoNear命令查詢并過濾 { category: "Parks" } 相匹配的數(shù)據(jù)跛梗,按照距離指定的GeoJSON最近的順序排序
db.runCommand(
{
geoNear: "places",
near: { type: "Point", coordinates: [ -73.9667, 40.78 ] },
spherical: true,
query: { category: "Parks" }
}
)
傳統(tǒng)坐標(biāo)對數(shù)據(jù)
創(chuàng)建集合-插入數(shù)據(jù)-建立索引
db.createCollection("location")
db.location.save( {_id: "A", position: [0.1, -0.1]} )
db.location.save( {_id: "B", position: [1.0, 1.0]} )
db.location.save( {_id: "C", position: [0.5, 0.5]} )
db.location.save( {_id: "D", position: [-0.5, -0.5]} )
db.location.ensureIndex( {position: "2d"} )
查詢point(0,0),半徑0.7附近的點(diǎn)
db.location.find( {position: { $near: [0,0], $maxDistance: 0.7 } } )
查詢[0.25, 0.25], [1.0,1.0]區(qū)域附近的點(diǎn)
db.location.find( {position: { $geoWithin: { $box: [ [0.25, 0.25], [1.0,1.0] ] } } } )
參考 mongodb官方文檔
到此mongodb地理數(shù)據(jù)支持的基礎(chǔ)知識已經(jīng)介紹完寻馏,請看下篇實戰(zhàn)篇,我們還是會生成600w調(diào)數(shù)據(jù)mongodb方案進(jìn)行測試核偿。
文章同步發(fā)布在博客诚欠,LBS-查找附近的人-mongodb實現(xiàn)-基礎(chǔ)知識