基于地理位置的应用越来越多,该功能可以查找距离当前位置最近的地点,例如美团、共享单车等。MongoDB为LBS应用提供了解决方案:基于2dSphere索引,我们可以基于该特性创建LBS应用。下面通过一个案例说明如何用mongoDB做位置搜索。
如下图所示。假设我们有以下的坐标点 A B C D E F G, 分别代表一些采集到地理位置的商店。那么,我们怎么才能获取到距离自己最近的商店呢?我们有一个集合是商店shop,分别保存了商店的名称和地理位置。
(1)创建商店的集合
db.createCollection("shop")
(2)为字段位置location建立索引,类型:2dsphere
db.shop.createIndex({"location":"2dsphere"})
(3)插入商店的测试数据
在前面我们为位置创建了2dsphere索引,这里需要插入的是GeoJson数据。GeoJson的格式是
{ type: ‘GeoJSON type’ , coordinates: ‘coordinates’ }
其中type指的是类型,可以是Point(本例中用的)。除此之外,还有LineString,Polygon等类型,coordinates是一个坐标数组。
可以到官网 https://docs.mongodb.com/manual/reference/geojson/ 参考其他类型。
db.shop.insert({name:"A",location:{type:"Point",coordinates:[105.754484701156,41.689607057699]}})
db.shop.insert({name:"B",location:{type:"Point",coordinates:[105.304045248031,41.783456183240]}})
db.shop.insert({name:"C",location:{type:"Point",coordinates:[105.084318685531,41.389027478812]}})
db.shop.insert({name:"D",location:{type:"Point",coordinates:[105.831388998031,41.285916385493]}})
db.shop.insert({name:"E",location:{type:"Point",coordinates:[106.128706502914,42.086868474465]}})
db.shop.insert({name:"F",location:{type:"Point",coordinates:[105.431074666976,42.009365053841]}})
db.shop.insert({name:"G",location:{type:"Point",coordinates:[104.705977010726,41.921549795110]}})
(4)查询附近的商店
db.runCommand({
geoNear:"shop",
near:{type:"Point",coordinates:[105.794621276855,41.869574065014]},
spherical:true,
minDistance:25000,
maxDistance:40000,
})
参数分别是:
- geoNear: 集合名称
- near: 就是基于那个点进行搜索
- spherical: 是个布尔值,如果为true,表示将计算实际的物理距离比如两点之间有多少km,若为false,则会基于点的单位进行计算
- minDistance: 搜索的最小距离,这里的单位是米
- maxDistance: 搜索的最大距离
数据返回:
{
"results" : [
{
"dis" : 33887.541661125804,
"obj" : {
"_id" : ObjectId("5d8f7f4d54cc000ac9ebac97"),
"name" : "F",
"location" : {
"type" : "Point",
"coordinates" : [
105.431074666976,
42.009365053841
]
}
}
},
{
"dis" : 36734.974878412715,
"obj" : {
"_id" : ObjectId("5d8f7f4d54cc000ac9ebac96"),
"name" : "E",
"location" : {
"type" : "Point",
"coordinates" : [
106.128706502914,
42.086868474465
]
}
}
}
],
"stats" : {
"nscanned" : 7,
"objectsLoaded" : 4,
"avgDistance" : 35311.258269769256,
"maxDistance" : 36734.974878412715,
"time" : 5128
},
"ok" : 1
}
在results中,我们搜索到了点F和E。每个文档都加上了一个dis字段,他表示这个点离你搜索点的距离。比如说,在结果中name为F的点的dis为33887.5416611258。表示F点距离搜索点的距离是33887米。