GeoJSON 和 MongoDB:将点存储为 GeoJSON.Point 值得吗?

17

随着2.3 >的引入,MongoDB在处理和查询位置数据方面变得更加有用。MongoDB将文档存储为BSON格式,因此每个文档都包含所有文档字段,这显然可能会导致比传统关系型数据库更大的数据库。

我曾经将折线和多边形存储为一系列索引点,还有一个额外的字段表示每条线的顺序(我这样做是为了确保一致性,因为我使用JavaScript,所以点并不总是按照它们的正确顺序存储)。大致上如下:

polyline: {
  [
    point: [0,0],
    order: 0
  ],
  [
    point: [0,1],
    order: 1
  ]
}

然而现在我使用的是:

polyline: {
  type: 'LineString',
  coordinates: [
    [0,0],
    [1,0]
  ]
}

我注意到文档大小有所改善,因为某些折线可以有多达500个点。

但是,我想知道将我的所有Point数据存储为GeoJSON的好处是什么。我对文档大小的增加感到沮丧,例如:

loc: [1,0]

比...好得多。

loc: {
  type: 'Point',
  coordinates: [0,1]
}

因此更容易处理,

我的问题是:

与将点存储为2点数组相比,将点存储为 GeoJSON 对象是否更好/推荐?

我考虑了以下内容:

  • 大小约束:我可能会有数百万个具有位置的文档,这可能会影响集合的大小,并潜在地影响我的钱包。
  • 一致性:最好使用 lng,lat 格式来处理每组坐标,而不是针对点采用 lat,lng ,并针对所有其他位置功能使用 lng,lat
  • 方便性:如果我获取一个点,并使用 $geoWithin $geoIntersects ,则在将其用作 query 参数之前,我无需先将其转换为GeoJSON。

我不确定的是:

  • 未来MongoDB是否会停止支持 loc:[x,y]
  • 2d 相比,是否有任何 2dsphere 的索引优势
  • 是否会有任何计划中的 GeoJSON 添加到MongoDB可能会导致需要上述一致性的情况。

在我的数据仍然可管理的情况下,我宁愿转移到 GeoJSON ,而不是在未来承受很大压力时再进行切换。

我可以请求一个经过彻底(即使略微)思考的答案。我不会立即选择正确的答案,以便评估任何回复

我也不确定SO是否是提出问题的合适场所,因此如果DBA是更合适的地方,我将在那里移动问题。我选择SO是因为这里有很多与MongoDB相关的活动

3个回答

17

我建议使用新的GeoJSON格式。虽然我不认为有任何关于停止支持旧格式的宣布,但他们将其称为legacy应该表明了他们的看法。

使用2dsphere而不是2d有一些索引优点。

  • 首先,它实际上是基于地球作为一个球体来计算查询的。 2d索引的缺点之一是它没有考虑到这一点,这意味着如果您对查询涵盖的实际区域感兴趣而不是基本的lat / lngs,则必须自己处理转换。
  • 如果要执行“按最近顺序获取此区域的100个结果”之类的操作,则可以使用复合索引,此时2dsphere是唯一的选择。
  • 能够使用geoIntersects查询。
  • geoWithin几何查询需要使用geoJSON格式。

还有一件重要的事情要注意,就是您需要确保所使用的查询受所使用的索引支持。例如,如果您使用2dsphere,则无法使用$box查询,因为它不会被索引 - 但是mongo不会警告您 - 结果只会执行表扫描,并且速度非常慢!

Mongo提供了一个兼容性表,其中列出了可以与哪些索引一起使用的查询


我接受你的答案。你的第二点是说服我的关键。我曾经读过它,但忘记了现在可以在2dsphere上使用复合索引。 - nevi_me

4
是的,我认为这很值得。根据我的地理空间信息系统经验,最好将位置数据存储在有用且可转移的标准中。MongoDB中的GeoJSON支持WGS84基准标准。
在MongoDB中,$near运算符可以搜索传统2D坐标和GeoJSON坐标。在传统2D坐标集合上,$near返回一个最接近的排序集合。$geoNear返回一个最接近的排序集合,其中包含来自搜索点元数据的距离。
另一个好处是能够使用其他地理空间查询(即$geoWithin和$geoIntersect),特别是如果您存储其他GeoJSON类型(折线,多边形)
最后虽然基本的球面距离查询被2d索引支持,但如果您的数据主要是经度和纬度,请考虑切换到2dsphere索引。希望这些信息能够给您在处理位置数据时提供一些思路。

从我的经验来看,我可以使用所有Mongo的地理查询与传统的pair一起使用,包括$geoNear。因此,我没有注意到任何查询类型上的差异。我有另一个应用程序,它使用GeoJSON存储所有位置数据,所以我是在比较这两者之间的区别。我将点数据存储在lat、lng格式中,并编写了一个实用程序,将GeoJSON转换为数组并返回。因此,从方便性来说,这没有任何区别。我更担心未来与Mongo 2.6等版本的兼容性。 - nevi_me

2
如果您的数据库中只存储点几何信息,但想支持对该数据进行多个不同的GeoJSON查询,则请注意,可以将点以遗留坐标对格式存储并使用2dsphere索引。
mongoose的GeoJSON支持(MongoDB >= 2.4)的发布说明提供了以下示例:
遗留坐标对上的2dsphere索引:
new Schema({ 
    loc: { type: [Number], index: '2dsphere'}
});

使用2dsphere索引对旧坐标对进行GeoJSON查询:
var geojsonPoly = { 
    type: 'Polygon', 
    coordinates: [[[-5,-5], ['-5',5], [5,5], [5,-5],[-5,'-5']]] 
};

Model.find({ loc: { $within: { $geometry: geojsonPoly }}});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接