eddik 发表于 2017-12-15 17:30:12

MongoDB的地理位置查询,以及和mysql的使用对比

  MongoDB的一个特色就是具有丰富的查询接口,比如地理位置查询。
  在地理位置查询上,MongoDB有着比传统关系型数据库的优势,下面举个例子。
  当前移动互联网应用,按用户离目标门店距离排序上的场景很多。
  比如:
  一张门店表shop_list,表结构字段包括shop_id,shop_name,lng,lat (门店id,门店名称,以及门店的经纬度等)。
  现收集到当前用户的所处位置的经纬度是,经度116.30759,纬度40.05748。获取距离用户1000m以内的100家门店,按照距离从近到远排序。
  MySql的查询语句如下:
  

SELECT shop_id,shop_name,lng,lat, ROUND(6378.138*2*ASIN(SQRT(POW(SIN((40.05748*PI()/180-lat*PI()/180)/2),2)+COS(40.05748*PI()/180)*COS(lat*PI()/180)*POW(SIN((116.30759*PI()/180-lng*PI()/180)/2),2)))*1000) AS distance  

FROM shop_list  

HAVING distance < 1000  
ORDER BY distance LIMIT 100;
  

  一个这样的计算方法,显然mysql性能比较差。
  下面的这个计算方法更快一些,效果和上面的几乎差不多,只是距离distance并不真实。如果只想按照距离排序查出结果是没问题的。
  

SELECT  shop_id ,
  shop_name ,
  lng ,
  lat ,
POWER(lat - 40.05748 , 2) + POWER(lng - 116.30759 , 2) * POWER(COS((lat + 40.05748) / 2) , 2) AS distance  

FROM  shop_list
  

HAVING  distance
< 1000  
ORDER BY
  distance
  
LIMIT 100;
  

  换做MongoDB会如何呢?
  首先,要明确MongoDB在使用距离查询时,存储的经纬度结构要类似这样才可以:
  

'point' : [  116.299,
  40.053
  

]  
或者:
  

  
'point' : {
  'lng' : 116.299,
  'lat' : 40.053
  
}
  

  然后给经纬度的point做一个2dSphere索引。具体参考官方文档: 
  

db.shop_list.createIndex({"point":"2dsphere"})  

  第三个用法可以得出距离值:
  

#这个点的附近  
db.shop_list.find({
'point':{$nearSphere: }})  

  
#这个点的附近1000米
  
db.shop_list.find({point: { $geoWithin: { $centerSphere:
[ [ 116.30759, 40.05748 ], 1000/6378137 ] } } })  

  
#这个点的附近1000米的10个门店,并且有距离计算值
  
db.runCommand({ geoNear : "shop_list" , near :
[ 116.30759, 40.05748], num : 10 , spherical:true, distanceMultiplier: 6378137, maxDistance:1000/6378137})  
页: [1]
查看完整版本: MongoDB的地理位置查询,以及和mysql的使用对比