MongoDB文档:
[{
_id: '123213',
elevation: 2300,
area: 25
},
{
_id: '343221',
elevation: 1600,
area: 35,
},
{
_id: '545322',
elevation: 500
area: 12,
},
{
_id: '234234',
elevation: null,
area: 5
}]
我希望在给定的高程间隔上对这些进行分组并总结区域属性。
所以预期的输出是:
[{
interval: '1501-3000',
count: 2,
summarizedArea: 60
},
{
interval: '0-1500',
count: 1,
summarizedArea: 12,
},
{
interval: 'N/A',
count: 1,
summarizedArea: 5
}]
如果可能,我想使用aggregation pipeline
。
也许有$range
的东西?或$gte
和$lte
?
答案 0 :(得分:1)
您可以使用MongoDB 3.4中引入的$bucket
来实现此目的:
db.collection.aggregate([
{
$bucket: {
groupBy: "$elevation",
boundaries: [
0,
1500,
3000,
5000
],
default: 10000,
output: {
"count": {
$sum: 1
},
"summarizedArea": {
$sum: "$area"
}
}
}
}
])
输出:
[
{
"_id": 0,
"count": 1,
"summarizedArea": 12
},
{
"_id": 1500,
"count": 2,
"summarizedArea": 60
},
{
"_id": 10000,
"count": 1,
"summarizedArea": 5
}
]
你可以在这里试试:mongoplayground.net/p/xFe7ZygMqaY
答案 1 :(得分:1)
正如Feliix建议$bucket应该做的那样,但边界应该略有不同,以便与负值和N/A
值一起使用:
db.collection.aggregate([
{
$bucket: {
groupBy: "$elevation",
boundaries: [ -Number.MAX_VALUE, 0, 1501, 3001, Number.POSITIVE_INFINITY ],
default: Number.NEGATIVE_INFINITY,
output: {
"count": { $sum: 1 },
"summarizedArea" : { $sum: "$area" }
}
}
}
])
可以将下面的格式化阶段添加到管道中以调整响应的形状:
{ $group: {
_id: null,
documents: { $push: {
interval: { $let: {
vars: {
idx: { $switch: {
branches: [
{ case: { $eq: [ "$_id", -Number.MAX_VALUE ] }, then: 3 },
{ case: { $eq: [ "$_id", 0 ] }, then: 2 },
{ case: { $eq: [ "$_id", 1501 ] }, then: 1 },
{ case: { $eq: [ "$_id", 3001 ] }, then: 0 }
],
default: 4
} }
},
in: { $arrayElemAt: [ [ ">3000", "1501-3000", "0-1500", "<0", "N/A" ], "$$idx" ] }
} },
count: "$count",
summarizedArea: "$summarizedArea"
} }
} }
$group _id: null
$push将所有群组转换为单个文档的数组。
$let将前一阶段的$_id
映射到数组[ ">3000", "1501-3000", "0-1500", "<0", "N/A" ]
中定义的区间的文本标签。为此,它使用$switch计算标签的idx
索引。
在应用程序级别实现逻辑必须更简单,除非你绝对需要在管道中执行它。