随着2.3 >
的引入,MongoDB在位置数据处理和查询方面变得更加有用。MongoDB将文档存储为BSON,因此每个文档都具有所有文档字段,这显然可能导致比传统RMDBS更大的数据库。
我曾经将折线和多边形存储为一系列索引点,并使用一个额外的字段表示每行的顺序(我这样做是为了确保使用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]
}
,因此更容易处理。
我的问题是:是否更好/建议将点存储为GeoJSON
对象而不是2点数组?
我考虑了以下几点:
- 大小限制:我可能有数百万个文档与一个位置,这可能会影响集合的大小,并可能影响我的口袋。 一致性:最好处理
- 便利性:如果我抓住一个点,并使用
$geoWithin
或$geoIntersects
与它,我不需要将其转换为GeoJSON之前使用它作为query
参数。
lng, lat
格式的每一组坐标,而不是坚持lat, lng
格式的点,而前者用于我所有的其他位置特征。我不确定的是:
- 将来MongoDB是否会放弃
loc: [x,y]
的支持 - 与
2d
相比,2dsphere
对索引的好处 - 是否任何计划的
GeoJSON
添加到MongoDB可能会导致需要上面提到的一致性
我宁愿在我的数据仍然可以管理的时候转移到GeoJSON
,而不是在未来的很多压力下切换。
我可以请你给我一个深思熟虑的答案吗?我不会很快选择一个正确的答案,所以我可以评估所有的回答。
我也不确定SO是否是提出问题的正确位置,所以如果DBA是更合适的位置,我将把问题移到那里。我选择了SO,因为这里有很多MongoDB相关的活动。
我建议使用新的GeoJSON格式。虽然我不相信任何关于放弃对旧格式的支持的声明已经做出,但他们将其称为遗产的事实应该表明他们的意见。
使用2dsphere比使用2d有一些索引方面的好处。
- 首先,它实际上是基于地球是一个球体来计算查询。2d索引的缺点之一是它没有考虑到这一点,这意味着如果您对查询所覆盖的实际区域而不是基本的lat/lng感兴趣,则必须自己处理转换。
- 使用复合索引的能力,如果你想做一些事情,比如"从这个区域最近的100个结果首先",那么2dsphere是你唯一的选择。
- 使用geoIntersects查询的能力。
- geoWithin几何查询要求你使用geoJSON格式。
另一件需要注意的重要事情是,您需要确保所使用的索引支持您正在使用的查询。例如,如果您使用2dsphere,则不能使用$box查询,因为它不会被索引-然而mongo不会警告您 -结果将只执行表扫描,并且将非常慢!
Mongo提供了一个兼容性图表,显示哪些查询可以与哪些索引一起使用
是的,我认为这是值得的。从我使用地理空间信息系统的经验来看,最好将您的位置数据存储在一个有用且可转移的标准中。MongoDB中的GeoJSON支持WGS84数据标准。
在MongoDB中,$near操作符可以搜索遗留的2d坐标和GeoJSON坐标。对于遗留的2d坐标集合,$near返回最近的第一个排序集合。$geoNear返回与搜索点元数据距离最近的第一个排序集合。
另一个好处是能够使用其他地理空间查询(i。e $geoWithin和$geoIntersect)特别是如果您存储其他GeoJSON类型(Polyline, Polygon)
最后,虽然2d索引支持使用球面距离的基本查询,但如果您的数据主要是经度和纬度,请考虑使用2dsphere索引。
我希望这些信息能给你一些思考点,关于如何处理你的位置数据。
如果您只在数据库中存储点几何,但希望在该数据上支持多个不同的GeoJSON查询,那么请注意,可以以传统坐标对格式存储点和使用2dsphere
索引。
mongoose的GeoJSON支持(MongoDB>= 2.4)的发布说明给出了以下示例:
2dsphere
在旧坐标对上的索引:
new Schema({
loc: { type: [Number], index: '2dsphere'}
});
GeoJSON
查询,使用2dsphere
索引:
var geojsonPoly = {
type: 'Polygon',
coordinates: [[[-5,-5], ['-5',5], [5,5], [5,-5],[-5,'-5']]]
};
Model.find({ loc: { $within: { $geometry: geojsonPoly }}});