就 mongoDb 而言,GeoJSON 和 Legacy 坐标对有啥区别?

Posted

技术标签:

【中文标题】就 mongoDb 而言,GeoJSON 和 Legacy 坐标对有啥区别?【英文标题】:What is difference between GeoJSON & Legacy coordinate pairs in terms of mongoDb?就 mongoDb 而言,GeoJSON 和 Legacy 坐标对有什么区别? 【发布时间】:2013-11-29 17:49:40 【问题描述】:

我正在尝试使用 mongoDb 的 $geoNear 聚合运算符以下列方式计算用户与当前位置的距离:

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

当前位置类似于:

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

我的收藏是以下类型(使用猫鼬):

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

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

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

现在我面临的问题是,如果我使用上面提到的 currentLocation(以 GeoJSON 的形式)进行查询,我会得到奇怪的距离(非常大的数字),但如果我使用 currentLocation.coordinates,即使用旧坐标对( [-122.1575745, 37.4457966]),我得到了正确的结果。但是mongoDb docs for geoNear 明确表示我们可以同时使用 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] 

【问题讨论】:

【参考方案1】:

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

> 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")

Warsaw PL 和 Stockholm 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

两种解决方案之间的差异可能会更小,但它只是一个 FP 算法。

> Math.abs(810.0952846015052 - 810.9980748260651)
0.902790224559908

当您将find 命令与$near 运算符一起使用时。当您在旧坐标对上创建简单的2d 索引时,可以使用$near: Stockholm.location.coordinates$near: $geometry: Stockholm.location 来查询它。如果您有2dsperhical,则只有$near: $geometry: Stockholm.location 可以工作。

【讨论】:

正如你所说,对准确性没有影响......但它对效率有何影响......

以上是关于就 mongoDb 而言,GeoJSON 和 Legacy 坐标对有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB:如何确定 GeoJson LineString 和具有半径的点的交集

文件转换-cad转geojson

如何在 Spring Boot 中从 mongodb 更改 geojson (GeoJsonPolygon) 的编组?

如何在 MongoDB 2.4.x 中存储附加数据以使其符合 geoJSON 格式

Node.js如何将geojson从mongodb传递给我可以在前端使用的对象

C#MongoDb api - Geojson几何存储成一个类