用mongodb的地理空间索引实现“找到离当前位置最近的N个场所

数据库 admin 1660℃ 0评论

应用场景:现在好多的手机APP中都会有周边的功能,比如百度地图的周边、QQ或微信的周边朋友、再或者某某找陌生人 都会都类似的,首先APP要先开启你的定位功能确定你所在的位置,再根据你所在位置找到周边规定范围内的 人或物。

http://www.i1502.com/?p=164 这篇文件就是专门介绍 MongoDB中的 地理索引的具体的使用方式。

刚才我看了一般头还是晕晕的。所以我自己也做了一个小小的例子:

首先 启动 MongoDB服务

bin\mongod    -f  conf\mongo.conf

mongo.conf里面很简单就是指定 数据库路径、日志路径、端口、日志加载方式

  • dbpath = E:\WAMP\mongodb\data
  • logpath = E:\WAMP\mongodb\mg.log
  • port = 27017
  • logappend = true

选择数据库

>use i1502;

创建索引

>db.places.ensureIndex( { loc : "2d" } )

添加数据

>db.places.insert({address:"鼓楼",loc:[39.947340900402,116.40229600204]});
>db.places.insert({address:"三里屯",loc:[39.943395067604,116.45406355197]});
>db.places.insert({address:"西二旗",loc:[40.058091472573,116.31978682061]});
>db.places.insert({address:"奥林匹克公园",loc:[40.00320138923,116.40064231143]});
>db.places.insert({address:"朝阳门",loc:[39.929785488276,116.4401913793]});
>db.places.insert({address:"前门",loc:[39.904905884415,116.40470220318]});
>db.places.insert({address:"东单",loc:[39.916602616822,116.42417171748]});
>db.places.insert({address:"西单",loc:[39.916796650652,116.37928644539]});
>db.places.insert({address:"天安门",loc:[39.912093958503,116.40393612824]});
>db.places.insert({address:"建外SOHO",loc:[39.911030600388,116.44955711255]});
>db.places.insert({address:"国贸",loc:[39.915403952767,116.47137201271]});
.......

根据一个经纬度查询时间

> db.places.find({loc:{$near:[39.943395067604,  116.45406355197]}}).limit(1);
"_id" : ObjectId("5480627c8e2a5318d8e5d51a"), "address" : "三里屯", "loc" : [39.943395067604,  116.45406355197 ] }

 

> db.places.find({loc:{$near:[39.943395067604,  116.45406355197]}}).limit(2);
"_id" : ObjectId("5480627c8e2a5318d8e5d51a"), "address" : "三里屯", "loc" : [39.943395067604,  116.45406355197 ] }
"_id" : ObjectId("548062658e2a5318d8e5d517"), "address" : "朝阳门", "loc" : [39.929785488276,  116.4401913793 ] }

 

> db.places.find({loc:{$near:[39.943395067604,  116.45406355197]}}).limit(3);
"_id" : ObjectId("5480627c8e2a5318d8e5d51a"), "address" : "三里屯", "loc" : [39.943395067604,  116.45406355197 ] }
"_id" : ObjectId("548062658e2a5318d8e5d517"), "address" : "朝阳门", "loc" : [39.929785488276,  116.4401913793 ] }
"_id" : ObjectId("5480604f8e2a5318d8e5d511"), "address" : "建外SOHO", "loc" :[39.911030600388,  116.44955711255 ] }

 

> db.places.find({loc:{$near:[39.943395067604,  116.45406355197]}}).limit(4);
"_id" : ObjectId("5480627c8e2a5318d8e5d51a"), "address" : "三里屯", "loc" : [39.943395067604,  116.45406355197 ] }
"_id" : ObjectId("548062658e2a5318d8e5d517"), "address" : "朝阳门", "loc" : [39.929785488276,  116.4401913793 ] }
"_id" : ObjectId("5480604f8e2a5318d8e5d511"), "address" : "建外SOHO", "loc" :[39.911030600388,  116.44955711255 ] }
"_id" : ObjectId("548060088e2a5318d8e5d510"), "address" : "国贸", "loc" : [39.15403952767,  116.47137201271 ] }

 

四次查询唯一改变的就是 limit();的参数

上面的查询寻找离(39.943395067604,  116.45406355197)最近的点并且按距离排序后返回(这里不需要增加排序参数)。使用limit()指定最大返回个数(默认返回100个):

这样基本的已经实现了根据一个地址获取周边人或物了,但是感觉有哪里不对!!!

> db.places.find({loc:{$near:[39.943395067604,  116.45406355197]}});
{ "_id" : ObjectId("548060088e2a5318d8e5d510"), "address" : "国贸", "loc" : [  39.915403952767,  116.47137201271 ] }
{ "_id" : ObjectId("5480604f8e2a5318d8e5d511"), "address" : "建外SOHO", "loc" :[  39.911030600388,  116.44955711255 ] }
{ "_id" : ObjectId("548060878e2a5318d8e5d512"), "address" : "天安门", "loc" : [ 39.912093958503,  116.40393612824 ] }
{ "_id" : ObjectId("548060b78e2a5318d8e5d513"), "address" : "西单", "loc" : [  39.916796650652,  116.37928644539 ] }
{ "_id" : ObjectId("5480621a8e2a5318d8e5d514"), "address" : "东单", "loc" : [  39.916602616822,  116.42417171748 ] }
{ "_id" : ObjectId("548062548e2a5318d8e5d515"), "address" : "东单", "loc" : [  39.916602616822,  116.42417171748 ] }
{ "_id" : ObjectId("5480625d8e2a5318d8e5d516"), "address" : "前门", "loc" : [  39.904905884415,  116.40470220318 ] }
{ "_id" : ObjectId("548062658e2a5318d8e5d517"), "address" : "朝阳门", "loc" : [ 39.929785488276,  116.4401913793 ] }
{ "_id" : ObjectId("5480626f8e2a5318d8e5d518"), "address" : "奥林匹克公园", "loc" : [  40.00320138923,  116.40064231143 ] }
{ "_id" : ObjectId("548062768e2a5318d8e5d519"), "address" : "西二旗", "loc" : [ 40.058091472573,  116.31978682061 ] }
{ "_id" : ObjectId("5480627c8e2a5318d8e5d51a"), "address" : "三里屯", "loc" : [ 39.943395067604,  116.45406355197 ] }
{ "_id" : ObjectId("548062888e2a5318d8e5d51b"), "address" : "鼓楼", "loc" : [  39.947340900402,  116.40229600204 ] }
.....

O~~~fuck~~~尼玛怎么出来这么多,我只要距离三里屯5公里的,怎么会有这么多!这时我们还有一个更好的参数去限制距离。maxDistance

 > db.places.find({loc:{$near:[39.943395067, 116.454],$maxDistance:0.05}}).limit(100);
{ "_id" : ObjectId("5480627c8e2a5318d8e5d51a"), "address" : "三里屯", "loc" : [ 39.943395067604, 116.45406355197 ] }
{ "_id" : ObjectId("548062658e2a5318d8e5d517"), "address" : "朝阳门", "loc" : [ 39.929785488276, 116.4401913793 ] }
{ "_id" : ObjectId("5480604f8e2a5318d8e5d511"), "address" : "建外SOHO", "loc" :[39.911030600388, 116.44955711255 ] }
{ "_id" : ObjectId("548060088e2a5318d8e5d510"), "address" : "国贸", "loc" : [39.915403952767, 116.47137201271 ] }
{ "_id" : ObjectId("5480621a8e2a5318d8e5d514"), "address" : "东单", "loc" : [39.916602616822, 116.42417171748 ] }

完成 收工!

转载请注明:My House » 用mongodb的地理空间索引实现“找到离当前位置最近的N个场所

喜欢 (2)
发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址