mongo php geonear_mongodb通过$geoNear进行坐标检索

这篇博客探讨了MongoDB 3.x版本相较于2.x在地理信息检索上的变化。通过示例展示了如何创建geo索引、插入数据以及使用find、aggregate和runCommand三种方式查询附近一公里的点。文中强调3.x版本的geoNear查询支持返回距离并按距离排序,同时解释了dis单位的转换方法。对于开发涉及地理位置数据处理的人员具有参考价值。
摘要由CSDN通过智能技术生成

最近的项目涉及带geo信息的多源数据融合,发现mongo3.x的geo检索跟2.x有点变化,在这里mark一下。

//1.建立geo索引

db.point.ensureIndex({"geo":"2d"});

//"geo"格式说明:

[

116.279943 #lng经度

40.049971, #lat纬度

]

//2.插入示例数据

db.point.insert({ "@id" : 1, "@geo" : [ 116.305297, 40.041993 ], "@bucket":["稻香村"], "@bucket_sign":["19d40bb2165c198560278e7bc3b2c5e5"] ,"name":"稻香村上地店"})

db.point.insert({ "@id" : 2, "@geo" : [ 116.305306, 40.041995 ], "@bucket":["稻香村"], "@bucket_sign":["19d40bb2165c198560278e7bc3b2c5e5"] ,"name":"稻香村西二旗店" })

db.point.insert({ "@id" : 3, "@geo" : [ 116.305309, 40.041993 ], "@bucket":["海底捞"], "@bucket_sign":["f6c832afc1c578ee731273c14a0245b4"] ,"name":"海底捞西二旗店" })

db.point.insert({ "@id" : 4, "@geo" : [ 116.279943,40.049971 ], "@bucket":["海底捞"], "@bucket_sign":["f6c832afc1c578ee731273c14a0245b4"] ,"name":"海底捞上地店" })

db.point.insert({ "@id" : 5, "@geo" : [ 116.225901,39.773136 ], "@bucket":["海底捞"], "@bucket_sign":["f6c832afc1c578ee731273c14a0245b4"] ,"name":"海底捞房山长阳店" })

//3.查询附近1公里的点示例:

1)find标准查询(仅mongodb2.x版本支持,不能返回距离)

db.point.find({"geo ":{ $near : [116.279943,40.049971] , $maxDistance : 1/111.12},"@bucket_sign" : [ "f6c832afc1c578ee731273c14a0245b4"}) 返回格式: { "_id" : ObjectId("59f8418c278994d6d2e77c9a"), "@id" : 4, "@geo" : [ 116.279943, 40.049971 ], "@bucket" : [ "海底捞" ], "@bucket_sign" : [ "f6c832afc1c578ee731273c14a0245b4" ], "name" : "海底捞上地店", "dist" : { "calculated" : 0, "location" : [ 116.279943, 40.049971 ] } } { "_id" : ObjectId("59f8418c278994d6d2e77c99"), "@id" : 3, "@geo" : [ 116.305309, 40.041993 ], "@bucket" : [ "海底捞" ], "@bucket_sign" : [ "f6c832afc1c578ee731273c14a0245b4" ], "name" : "海底捞西二旗店", "dist" : { "calculated" : 2.33435844594686, "location" : [ 116.305309, 40.041993 ] } } { "_id" : ObjectId("59f8418c278994d6d2e77c9b"), "@id" : 5, "@geo" : [ 116.225901, 39.773136 ], "@bucket" : [ "海底捞" ], "@bucket_sign" : [ "f6c832afc1c578ee731273c14a0245b4" ], "name" : "海底捞房山长阳店", "dist" : { "calculated" : 31.12581912580905, "location" : [ 116.225901, 39.773136 ] } } 2)aggregate聚合查询 返回格式与find相同。参数中$maxDistance为经纬弧度(1° latitude = 111.12 kilometers)即 1/111.12,表>示查找附近一公里。 db.point.aggregate([{$geoNear:{near:[116.279943,40.049971],distanceField: "dist.calculated",maxDistance: 100/111.12,query:{"@bucket_sign":"f6c832afc1c578ee731273c14a0245b4"},includeLocs: "dist.location",uniqueDocs: true,num: 5,spherical:true,"distanceMultiplier": 6371}}]) 返回同1)find格式3)runCommand命令方式

db.runCommand({geoNear:"point",near:[116.305207,40.042053 ], maxDistance : 1/111.12,query: { "@bucket":"海底捞" }})

返回格式:

{ "ns" : "point", "near" : "", "results" : [ { "dis" : 0.0001138771267725113, "obj" : { "_id" : ObjectId("59eeeed3b5fbf3fa598cd4b0"), "@id" : 4, "@geo" : [ 40.041995, 116.305305 ], "@bucket" : [ "海底捞" ], "@bucket_sign" : [ "f6c832afc1c578ee731273c14a0245b4" ], "name" : "海底捞西北旺店" } }, { "dis" : 0.00011833849754085601, "obj" : { "_id" : ObjectId("59eeeed3b5fbf3fa598cd4af"), "@id" : 3, "@geo" : [ 40.041993, 116.305309 ], "@bucket" : [ "海底捞" ], "@bucket_sign" : [ "f6c832afc1c578ee731273c14a0245b4" ], "name" : "海底捞西二旗店" } } ], "stats" : { "time" : 2, "btreelocs" : 0, "nscanned" : 19, "objectsLoaded" : 10, "avgDistance" : 0.00011610781215668365, "maxDistance" : 0.00011833849754085601, "shards" : [ "ucp_shard_14", "ucp_shard_3", "ucp_shard_8" ] }, "ok" : 1 }

注1:mongodb3.x版本的两种geoNear查询方式都支持返回距离并按距离正序排序。

注2:使用geoNear获得的结果里dis的单位,有两种情况:

1)spherical设为false(默认),dis的单位与坐标的单位保持一致

如果保存的是longitude/latitude,则dis的单位就是经度(或者纬度,单位是一致的)

如果保存的是meter,则dis的单位就是meter

2)spherical设为true,dis的单位是弧度

想要换算成公里(km)的话,

要么在程序里做,要么使用distanceMultiplier参数来定义转换方式:

对应于1)

如果要保存的坐标是经纬度,要计算的是公里,可设置 distanceMultiplier: 111

如果要计算英里,可将111换成69

对应于2)

如果要计算公里,可设置 distanceMultiplier: 6371

如果要计算英里,则需要把6371换成3959

yan 17.10.24

参考:

http://www.cnblogs.com/shanyou/p/3494854.html

http://www.dewen.net.cn/q/7412

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值