MongoDB聚合,按值间隔分组,

MongoDB聚合,按值间隔分组,,mongodb,aggregation-framework,Mongodb,Aggregation Framework,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 }] 我想按给定的标高间隔对这些属性进行分组,并总结面积属性 第

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
}]
我想按给定的标高间隔对这些属性进行分组,并总结面积属性

  • 第1组:<0
  • 第2组:0-1500
  • 第三组:1501-3000
  • 第4组:>3000
因此,预期产出为:

[{
   interval: '1501-3000',
   count: 2,
   summarizedArea: 60 
},
{
   interval: '0-1500',
   count: 1,
   summarizedArea: 12,
},
{
   interval: 'N/A',
   count: 1,
   summarizedArea: 5
}]
如果可能,我想使用
聚合管道


可能是
$range
?或者是
$gte
$lte
的组合?

您可以使用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
  }
]

您可以在这里尝试:

您可以使用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
  }
]
您可以在这里尝试:

正如Feliix建议的那样,应该完成这项工作,但是边界应该稍有不同,以便更好地处理负值和
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:{
变量:{
idx:{$switch:{
分支机构:[
{case:{$eq:[“$\u id”,-Number.MAX\u VALUE]},然后:3},
{case:{$eq:[“$\u id”,0]},然后:2},
{case:{$eq:[“$_id”,1501]},然后:1},
{case:{$eq:[“$\u id”,3001]},然后:0}
],
默认值:4
} }
},
在:{$arrayElemAt:[[”>3000、“1501-3000”、“0-1500”、“3000”、“1501-3000”、“0-1500”中,正如Feliix所建议的那样,“应该完成这项工作,但边界应该略有不同,以便更好地处理负值和
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:{
变量:{
idx:{$switch:{
分支机构:[
{case:{$eq:[“$\u id”,-Number.MAX\u VALUE]},然后:3},
{case:{$eq:[“$\u id”,0]},然后:2},
{case:{$eq:[“$_id”,1501]},然后:1},
{case:{$eq:[“$\u id”,3001]},然后:0}
],
默认值:4
} }
},

在:{$arrayElemAt:[[[]>3000”,“1501-3000”,“0-1500”,“3000”,“1501-3000”,“0-1500”,“是否有可能使$project作为问题输出?@Per,我肯定是它的,但是你能定义“作为问题”?是间隔标签吗(顺便说一句,它们在问题中看起来是错误的),带有数组而不是光标的单个文档,或文档的特定顺序?不是单个文档。每个组都有一个数组。带有间隔标签。顺序不重要。@抱歉,我没有得到它。它或者是带有组数组的单个文档:
[{interval:'1501-3000'…},{interval:'0-1500'…}]
或一个完全没有数组的文档光标:
{interval:'1501-3000'…},{interval:'0-1500'…}…
@Per,也是关于标签的。假设
高程
总是整数是公平的吗?有可能让$project将其输出为有问题的吗?@Per,我肯定是有问题的,但您能定义“有问题的”吗?是间隔标签(顺便说一句,他们在问题中看起来是错误的)、带有数组而不是光标的单个文档,还是文档的特定顺序?不是单个文档。每个组都有一个数组。带有间隔标签。顺序不重要。@抱歉,我没有理解它。它是带有组数组的单个文档:
[{interval:'1501-3000'..},{interval:'0-1500'..}…]
或者一个没有数组的文档光标:
{interval:'1501-3000'..},{interval:'0-1500'..}…
@Per,也关于标签。假设
高程
总是整数是否公平?