我们需要计算地理空间数据的最小边界矩形(MBR)。
在oracle中,我们具有SDO_AGGR_MBR
函数,MongoDB中是否有任何类似的函数。
"coord" : {
"type" : "Polygon",
"coordinates" : [
[
[
25.5377574375611,
42.8545750237221
],
[
47.7803203666229,
42.8545750237221
],
[
47.7803203661319,
52.0987759993153
],
[
25.5377574370701,
52.0987759993153
],
[
25.5377574375611,
42.8545750237221
]
]
]
}
我们具有如上所述的几何数据,但是坐标长度可能会有所不同。因此,我们需要从这些数据中找到minx
,miny
,maxx
和maxy
。
答案 0 :(得分:1)
我认为没有内置函数。但您只需执行以下操作;
db.collection.aggregate([
{
$unwind: "$coordinates"
},
{
$unwind: "$coordinates"
},
{
$group: {
_id: null,
minX: {
$min: { $arrayElemAt: [ "$coordinates", 0 ] }
},
maxX: {
$max: { $arrayElemAt: [ "$coordinates", 0 ] }
},
minY: {
$min: { $arrayElemAt: [ "$coordinates", 1 ] }
},
maxY: {
$max: { $arrayElemAt: [ "$coordinates", 1 ] }
}
}
}
])
首先用$unwind
解开coordinates
数组的位置(两次额外的[ ]
块),以便aggregate pipeline
可以对其进行迭代。然后,我们仅将$group
与a special operation一起使用mongoplayground来计算数组所有元素的最小/最大值。
这将使您收到请求的答复;
_id: null
检查https://medium.com/@felixblaschke/fancy-background-animations-in-flutter-4163d50f5c37
答案 1 :(得分:1)
最有效的方法是将$map
和$reduce
运算符与$let
一起使用。这使您可以通过处理数组的 inline 来处理每个文档,然后使用$min
和$max
运算符来获取边界值:
db.collection.aggregate([
{ "$replaceRoot": {
"newRoot": {
"$let": {
"vars": {
"m": {
"$map": {
"input": {
"$reduce": {
"input": "$coord.coordinates",
"initialValue": [],
"in": {
"$concatArrays": [ "$$value", "$$this"]
}
}
},
"in": {
"x": { "$arrayElemAt": [ "$$this", 0 ] },
"y": { "$arrayElemAt": [ "$$this", 1 ] }
}
}
}
},
"in": {
"_id": "$_id",
"coord": "$coord",
"minX": { "$min": "$$m.x" },
"minY": { "$min": "$$m.y" },
"maxX": { "$max": "$$m.x" },
"maxY": { "$max": "$$m.y" }
}
}
}
}}
])
输出将是:
{
"_id" : ObjectId("5d9330e95994eb7018f59218"),
"coord" : {
"type" : "Polygon",
"coordinates" : [
[
[
25.5377574375611,
42.8545750237221
],
[
47.7803203666229,
42.8545750237221
],
[
47.7803203661319,
52.0987759993153
],
[
25.5377574370701,
52.0987759993153
],
[
25.5377574375611,
42.8545750237221
]
]
]
},
"minX" : 25.5377574370701,
"minY" : 42.8545750237221,
"maxX" : 47.7803203666229,
"maxY" : 52.0987759993153
}
请注意$replaceRoot
聚合管道阶段的用法,因为这将允许带有$let
的嵌套表达式向文档提供全局变量,从而可以用于任何输出属性。
这里的$reduce
主要用于将标准GeoJSON形式的数组扁平化成一个坐标对数组,而没有附加的边界数组。
然后,将输入馈送到使用$map
的$arrayElemAt
,以便将每个坐标对重新映射到具有{{ 1}}和x
键。对于$let
的实际执行或 output 部分,这使事情变得更加简单。
注意:针对
$arrayElemAt
中的每个键使用$map
的另一种方法很可能是使用$zip
和$arrayToObject
:< / p>y
它在整体输出中具有相同的原理,但是利用
$zip
产生“成对”数组的优势,这对$arrayToObject
来说也是有效的输入,以产生最终的 object < / em>表单。
在最后一部分中,我们现在基本上有了一个对象数组,它们具有命名键 "in": {
"$arrayToObject": { "$zip": { "inputs": [ ["x","y"], "$$this" ] } }
}
和x
。 MongoDB提供了一种方便的方法来 remap ,简单地将名称命名为y
的那些命名键的值(其中"$$m.x"
表达式与$let
的命名变量和是我们的对象数组,而"$$m
部分当然意味着 仅.x
的值。这本身就是$map
语句的基本简写,适合这种特殊用法。
这些特定属性值的数组现在可以应用于$min
和$max
运算符,这就是获取x
和min
坐标的方式。边界矩形。
请注意,数组的内联运算符始终应优先于$unwind
。
$unwind
聚合流水线阶段是一种将数组元素基本上展平到单独文档中的古老介绍性方法。
当您实际上想对值作为数组中的键进行分组时,这是必需的,但是实际上不需要的大多数操作(如此操作)可以用更多的操作来完成现代方法。
$unwind
的使用实际上是一个巨大的性能损失,因为它的功能是将包含数组的字段的整个父文档内容复制到自己的新文档中。特别是在大型数据集中,由于I / O和内存使用量大大增加,这对性能产生了非常不利的影响。
主要的经验教训是,除非必须执行该操作(此处不是),否则您不应在聚合管道中使用$unwind
。它看起来 可能更容易理解,但是您的代码实际上通过包含它而正在损害正在运行的系统。
还请注意,如果您实际上不需要任何进一步的汇总处理所需的结果,那么在处理每个文档时在客户端进行编码可能会更干净。
例如,这是外壳的普通JavaScript版本:
max
具有完全相同的输出,并且几乎不像聚合管道所需的BSON运算符那样笨拙。