Mysql or Mongodb LBS快速实现方案
http://www.wubiao.info/470
前兩篇文章:
查找附近的xxx 球面距離以及Geohash方案探討 (http://www.wubiao.info/372)
微信、陌陌 架構(gòu)方案分析 (http://www.wubiao.info/401)
探討了,LBS查找附近的XXX;其中包括了,Mysql自定義存儲(chǔ)函數(shù)方案,以及通過GeoHash、redis自建索引方案。
===============================================================
今天分享兩種,利用GeoHash封裝成內(nèi)置數(shù)據(jù)庫(kù)函數(shù)的簡(jiǎn)易方案;
A:Mysql 內(nèi)置函數(shù)方案,適合于已有業(yè)務(wù),新增加LBS功能,增加經(jīng)緯度字段方可,避免數(shù)據(jù)遷移
B:Mongodb 內(nèi)置函數(shù)方案,適合中小型應(yīng)用,快速實(shí)現(xiàn)LBS功能,性能優(yōu)于A(推薦)
===============================================================
方案A: (MySQL Spatial)
1、先簡(jiǎn)歷一張表:(MySQL 5.0 以上 僅支持 MyISAM 引擎)
| 1 2 3 4 5 6 7 8 9 | CREATE TABLE address ( ????address CHAR(80) NOT NULL, ????address_loc POINT NOT NULL, ????PRIMARY KEY(address) ); |
空間索引:
| 1 | ALTER TABLE address ADD SPATIAL INDEX(address_loc); |
插入數(shù)據(jù):(注:此處Point(緯度,經(jīng)度) 標(biāo)準(zhǔn)寫法)
| 1 2 3 | INSERT INTO address VALUES('Foobar street 12', GeomFromText('POINT(30.620076 104.067221)')); INSERT INTO address VALUES('Foobar street 13', GeomFromText('POINT(31.720076 105.167221)')); |
查詢: 查找(30.620076,104.067221)附近 10 公里
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | SELECT? * ????FROM??? address ????WHERE?? MBRContains ????????????????????( ????????????????????LineString ????????????????????????????( ????????????????????????????Point ????????????????????????????????????( ????????????????????????????????????30.620076 + 10 / ( 111.1 / COS(RADIANS(104.067221))), ????????????????????????????????????104.067221 + 10 / 111.1 ????????????????????????????????????), ????????????????????????????Point ????????????????????????????????????( ????????????????????????????????????30.620076 - 10 / ( 111.1 / COS(RADIANS(104.067221))), ????????????????????????????????????104.067221 - 10 / 111.1 ????????????????????????????????????) ????????????????????????????), ????????????????????address_loc ????????????????????) |
方案B:
1、先建立一張簡(jiǎn)單的表user,兩條數(shù)據(jù)如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | { ??"_id": ObjectId("518b1f1a83ba88ca60000001"), ??"account": "simplephp1@163.com", ??"gps": [ ????104.067221, ????30.620076 ??] } { ??"_id": ObjectId("518b1dae83ba88d660000000"), ??"account": "simplephp6@163.com", ??"gps": [ ????104.07958, ????30.653936 ??] } |
其中,gps為二維數(shù)組,分別為經(jīng)度,緯度
(注:此處必須按照(經(jīng)度,緯度)順序存儲(chǔ)。我們平時(shí)表示經(jīng)緯度,都是(緯度,精度),此處這種方式有木有很親民)
2、使用之前,先建立二維索引
//建立索引 最大范圍在經(jīng)度-180~180
| 1 | db.user.ensureIndex({"gps":"2d"},{"min":-180,"max":180}) |
//刪除索引
| 1 | db.user.dropIndex({"gps":"2d"}) |
3、Mongodb有兩中方式可以查找附近的XXX;其中方案2)會(huì)返回距離(推薦)
1)標(biāo)準(zhǔn)查詢,為地球經(jīng)緯度查詢內(nèi)置;參數(shù)一為查詢條件利用$near查找附近,參數(shù)二$maxDistance為經(jīng)緯弧度(1° latitude = 111.12 kilometers)即 1/111.12,表示查找附近一公里。
| 1 | db.user.find({ gps :{ $near : [104.065847, 30.657554] , $maxDistance : 1/111.12} }) |
2)執(zhí)行命名方式,模擬成一個(gè)圓球;參數(shù)一指定geoNear方式和表名;參數(shù)二坐標(biāo),參數(shù)三是否為球形,參數(shù)四弧度(弧度=弧長(zhǎng)/半徑 一千米的弧度1000/6378000),參數(shù)五指定球形半徑(地球半徑)
| 1 | db.runCommand({geoNear:'user', near:[104.065847, 30.657554], spherical:true, maxDistance:1000/6378000, distanceMultiplier:6378000}); |
本條目發(fā)布于2013年05月28日。屬于DB、架構(gòu)、算法分類,被貼了?geohash、LBS、Mongodb、Mysql?標(biāo)簽。
總結(jié)
以上是生活随笔為你收集整理的Mysql or Mongodb LBS快速实现方案的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: xmpp整理笔记:xmppFramewo
- 下一篇: 52. SQL Server -- 表分