在 MongoDB 中截取一个 FeatureCollection
Intersept a FeatureCollection in MongoDB
我有一个充满奥地利州的 GeoJson,我想做一个查询,将某些州截获我的多边形作为输出。
这是我的查询:
db.GeoAustria.find(
{
'features.geometry':{
$geoIntersects:{
$geometry:{
type: "Polygon",
coordinates: [
[
[
16.21685028076172,
48.007381433478855
],
[
16.24225616455078,
47.98716432210271
],
[
16.256675720214844,
48.00669234420252
],
[
16.21685028076172,
48.007381433478855
]
]
]
}
}
}
}
)
但它为我提供了所有功能,包括那些不与多边形重叠的功能...
我在这个查询中的错误在哪里?
基本数组匹配误区在这里。输入集是一个文档,在一个 FeatureCollection
object 数组中有 95 个多边形。当您对此类事物执行 find() 时,任何相交的单个地理区域都会导致整个文档作为匹配项返回。这与:
完全相同
> db.foo.insert({x:["A","B","C"]})
WriteResult({ "nInserted" : 1 })
> db.foo.find({x:"A"});
{ "_id" : ObjectId("5fb1845b08c09fb8dfe8d1c1"), "x" : [ "A", "B", "C" ] }
返回整个文档,而不仅仅是元素“A”。
让我们假设您的 collection 中可能有不止一个大文档。此管道为 Baden 生成单一目标几何(我在您的输入集上对其进行了测试):
var Xcoords = [
[
[
16.21685028076172,
48.007381433478855
],
[
16.24225616455078,
47.98716432210271
],
[
16.256675720214844,
48.00669234420252
],
[
16.21685028076172,
48.007381433478855
]
]
];
var targ = {type: "Polygon", coordinates: Xcoords};
db.geo1.aggregate([
// First, eliminate any docs where the geometry array has zero intersects. In this
// context, features.geometry means "for each element of array features get the
// geometry field from the object there", almost like saying "features.?.geometry"
{$match: {"features.geometry": {$geoIntersects: {$geometry: targ}} }}
// Next, break up any passing docs of 95 geoms into 95 docs of 1 geom...
,{$unwind: "$features"}
// .. and run THE SAME $match as before to match just the one we are looking for.
// In this context, the array is gone and "features.geometry" means get JUST the
// object named geometry:
,{$match: {"features.geometry": {$geoIntersects: {$geometry: targ}} }}
]);
除此之外,我可能建议将 FeatureCollection
分解为既可索引(FeatureCollection
在 MongoDB 中不可索引)又更易于处理的内容。例如,针对您的 single-doc/many-polys 设计的这个小脚本 运行 将在 95 个文档中转换它并提供额外信息:
db.geo2.drop();
mainDoc = db.geo1.findOne(); // the one Austria doc
mainDoc['features'].forEach(function(oneFeature) {
var qq = {
country: "Austria",
crs: mainDoc['crs'],
properties: oneFeature['properties'],
geometry: oneFeature['geometry']
};
db.geo2.insert(qq);
});
db.geo2.aggregate([
{$match: {"geometry": {$geoIntersects: {$geometry: targ}} }}
]);
// yields same single doc output (Baden)
这使得匹配和过滤变得容易。有关 FeatureCollection
与 GeometryCollection
的更多信息,请参阅 https://www.moschetti.org/rants/hurricane.html。
我有一个充满奥地利州的 GeoJson,我想做一个查询,将某些州截获我的多边形作为输出。
这是我的查询:
db.GeoAustria.find(
{
'features.geometry':{
$geoIntersects:{
$geometry:{
type: "Polygon",
coordinates: [
[
[
16.21685028076172,
48.007381433478855
],
[
16.24225616455078,
47.98716432210271
],
[
16.256675720214844,
48.00669234420252
],
[
16.21685028076172,
48.007381433478855
]
]
]
}
}
}
}
)
但它为我提供了所有功能,包括那些不与多边形重叠的功能... 我在这个查询中的错误在哪里?
基本数组匹配误区在这里。输入集是一个文档,在一个 FeatureCollection
object 数组中有 95 个多边形。当您对此类事物执行 find() 时,任何相交的单个地理区域都会导致整个文档作为匹配项返回。这与:
> db.foo.insert({x:["A","B","C"]})
WriteResult({ "nInserted" : 1 })
> db.foo.find({x:"A"});
{ "_id" : ObjectId("5fb1845b08c09fb8dfe8d1c1"), "x" : [ "A", "B", "C" ] }
返回整个文档,而不仅仅是元素“A”。
让我们假设您的 collection 中可能有不止一个大文档。此管道为 Baden 生成单一目标几何(我在您的输入集上对其进行了测试):
var Xcoords = [
[
[
16.21685028076172,
48.007381433478855
],
[
16.24225616455078,
47.98716432210271
],
[
16.256675720214844,
48.00669234420252
],
[
16.21685028076172,
48.007381433478855
]
]
];
var targ = {type: "Polygon", coordinates: Xcoords};
db.geo1.aggregate([
// First, eliminate any docs where the geometry array has zero intersects. In this
// context, features.geometry means "for each element of array features get the
// geometry field from the object there", almost like saying "features.?.geometry"
{$match: {"features.geometry": {$geoIntersects: {$geometry: targ}} }}
// Next, break up any passing docs of 95 geoms into 95 docs of 1 geom...
,{$unwind: "$features"}
// .. and run THE SAME $match as before to match just the one we are looking for.
// In this context, the array is gone and "features.geometry" means get JUST the
// object named geometry:
,{$match: {"features.geometry": {$geoIntersects: {$geometry: targ}} }}
]);
除此之外,我可能建议将 FeatureCollection
分解为既可索引(FeatureCollection
在 MongoDB 中不可索引)又更易于处理的内容。例如,针对您的 single-doc/many-polys 设计的这个小脚本 运行 将在 95 个文档中转换它并提供额外信息:
db.geo2.drop();
mainDoc = db.geo1.findOne(); // the one Austria doc
mainDoc['features'].forEach(function(oneFeature) {
var qq = {
country: "Austria",
crs: mainDoc['crs'],
properties: oneFeature['properties'],
geometry: oneFeature['geometry']
};
db.geo2.insert(qq);
});
db.geo2.aggregate([
{$match: {"geometry": {$geoIntersects: {$geometry: targ}} }}
]);
// yields same single doc output (Baden)
这使得匹配和过滤变得容易。有关 FeatureCollection
与 GeometryCollection
的更多信息,请参阅 https://www.moschetti.org/rants/hurricane.html。