GeoJSON和Legacy坐标对在mongoDb方面有什么区别?

我想用mongoDb的$ geoNear聚合运算符来计算用户从当前位置的距离,方法如下:

'$geoNear': { near: currentLocation, distanceField: 'distance', spherical: true, } 

随着currentLocation是这样的:

 { "type" : "Point", "coordinates" : [ -122.1575745, 37.4457966 ] } 

我的collections是以下types(使用mongoose):

 users = [{ .... location : { // GeoJSON Point or I think it is ;) type: { type: String }, coordinates: [] } .... }] 

我正在使用索引(再次mongoose的语法):

 userSchema.index({ location: '2dsphere' }); 

现在我面临的问题是,如果我使用currentLocation(以GeoJSON的forms)查询,我得到奇怪的距离(非常大的数字),但是如果我使用currentLocation.coordinates,即使用传统的坐标对([-122.1575745 ,37.4457966]),我得到正确的结果。 但是geoNear的mongoDb文档清楚地表明,我们可以使用GeoJSON点或传统坐标对进行查询

我很想知道GeoJSON点和传统坐标对究竟有什么不同?

例如收集:

 { "_id" : ObjectId("5277679914c6d8f00b000003"), "location" : { "type" : "Point", "coordinates" : [ 106.6202887, -6.1293536 ] } } { "_id" : ObjectId("5277810148219d011c000003"), "location" : { "type" : "Point", "coordinates" : [ 106.6202887, -6.1293536 ] } } { "_id" : ObjectId("5281c7ba2dfd7bdc64000003"), "location" : { "type" : "Point", "coordinates" : [ -86.9248483, 33.4480108 ] } } { "_id" : ObjectId("5281c8b82dfd7bdc64000004"), "location" : { "type" : "Point", "coordinates" : [ -74.0087126, 40.7136487 ] } } { "_id" : ObjectId("5281c9782dfd7bdc64000005"), "location" : { "type" : "Point", "coordinates" : [ -122.1575745, 37.4457966 ] } } 

不正确的结果:

 [{"location":{"type":"Point","coordinates":[-122.1575745,37.4457966]},"dis":13.69288259318155}, {"location":{"type":"Point","coordinates":[-86.9248483,33.4480108]},"dis":12697164592.388557}, {"location":{"type":"Point","coordinates":[-74.0087126,40.7136487]},"dis":16328789117.58145}, {"location":{"type":"Point","coordinates":[106.6202887,-6.1293536]},"dis":55446284682.14049}, {"location":{"type":"Point","coordinates":[106.6202887,-6.1293536]},"dis":55446284682.14049}] 

让我们创build一些示例文档和地理空间索引:

 > db.foo.insert({name: "Warsaw", location: {"type" : "Point", "coordinates" : [21.016667, 52.233333]}}) > db.foo.insert({name: "Stockholm", location: {"type" : "Point", "coordinates" : [18.068611, 59.329444]}}) > db.foo.ensureIndex({"location": "2dsphere"}) 

华沙PL和斯德哥尔摩SE之间的距离大约为810公里,所以让我们来看看它是否按预期工作。 首先,我们可以为斯德哥尔摩提取文件。

 > Stockholm = db.foo.findOne({name: "Stockholm"}) 

现在我们可以使用geoNear运行查询了:

 > db.runCommand({ geoNear: 'foo', near: Stockholm.location.coordinates, spherical: true }) { "ns" : "test.foo", "results" : [ { "dis" : 6.558558954334308e-10, "obj" : { "_id" : ObjectId("52876ab0b12c6fc62f5d9311"), "name" : "Stockholm", "location" : { "type" : "Point", "coordinates" : [ 18.068611, 59.329444 ] } } }, { "dis" : 0.12715355275490586, "obj" : { "_id" : ObjectId("5287697eb12c6fc62f5d9310"), "name" : "Warsaw", "location" : { "type" : "Point", "coordinates" : [ 21.016667, 52.233333 ] } } } ], "stats" : { "time" : 9, "nscanned" : 3, "avgDistance" : 0.06357677670538088, "maxDistance" : 0.12715355275490586 }, "ok" : 1 } 

斯德哥尔摩和斯德哥尔摩之间的距离接近于0 。 斯德哥尔摩到华沙的距离是0.12715355275490586 。 当您使用传统坐标对运行查询时,您会得到弧度的结果,因此我们必须将该值乘以地球半径:

 > 0.12715355275490586 * 6371.0 810.0952846015052 

到现在为止还挺好。 让我们检查一下,如果我们使用geojson作为查询得到相似的结果。

 > db.runCommand({ geoNear: 'foo', near: Stockholm.location, spherical: true }) { "ns" : "test.foo", "results" : [ { "dis" : 0.004183114486663965, "obj" : { "_id" : ObjectId("52876ab0b12c6fc62f5d9311"), "name" : "Stockholm", "location" : { "type" : "Point", "coordinates" : [ 18.068611, 59.329444 ] } } }, { "dis" : 810998.0748260651, "obj" : { "_id" : ObjectId("5287697eb12c6fc62f5d9310"), "name" : "Warsaw", "location" : { "type" : "Point", "coordinates" : [ 21.016667, 52.233333 ] } } } ], "stats" : { "time" : 4, "nscanned" : 3, "avgDistance" : 405499.0395045898, "maxDistance" : 810998.0748260651 }, "ok" : 1 } 

斯德哥尔摩和斯德哥尔摩之间的距离再次接近0 。 斯德哥尔摩和华沙之间的距离是810998.0748260651。 当您使用GeoJSON运行geoNear查询时,距离是以米为单位计算的。 810998.0748260651大致等于810公里,这里没什么奇怪的。

 > 810998.0748260651 / 1000 810.9980748260651 

两种解决scheme之间的差异可能会更小,但它只是一个FPalgorithm。

 > Math.abs(810.0952846015052 - 810.9980748260651) 0.902790224559908 

当您使用$near操作符使用find命令时。 当您在传统坐标对上创build简单的2d索引时,可以使用{$near: Stockholm.location.coordinates}{$near: {$geometry: Stockholm.location} 。 如果你有2dsperhical只有{$near: {$geometry: Stockholm.location}将工作。