如何在使用mongo的$bucket聚合时检索桶边界?

5

我有一个包含20万多条记录的集合,其中包括一个浮点字段amountAwarded(例如12345.67、2342、22等)。我正在使用MongoDB根据以下边界将它们聚合到桶中:

amountAwarded: [
        {
            $bucket: {
                groupBy: '$amountAwarded',
                boundaries: [0, 10000, 50000, 100000, 1000000, Infinity],
                output: {
                    count: { $sum: 1 }
                }
            }
        }
    ]

这个工作符合预期,我得到了这个输出:
{
  "amountAwarded": [
    {
      _id: 0,
      count: 269
    },
    {
      _id: 10000,
      count: 67
    },
    // etc
  ]
}

我希望你能够在输出中引用存储桶边界,例如:
{
  "amountAwarded": [
    {
      _id: 0,
      count: 269,
      lowerBound: 0,
      upperBound: 9999
    }
  ]
}

这意味着我可以在前端构建一个列表,显示各个桶(例如 £0 - £9999)。
我最接近的方法是向输出中添加 $min: "$amountAwarded" (以及一个等效的 $max),这为我提供了存储在数据记录中的该字段的上限/下限值。但是这样做是不正确的,因为这些数字明显来自于数据(例如 8762),而不是桶的边界。
是否有可能在聚合管道中引用匹配的桶边界,或者我必须在 facet 完成后手动构建它?
1个回答

9
您可以自行定义边界,因此在下一阶段中,您可以使用indexOfArrayarrayElemAt的组合来使用addFields。类似于这样的代码:
db.collection.aggregate([
{
    $bucket: {
        groupBy: '$amountAwarded',
        boundaries: [0, 10000, 50000, 100000, 1000000, Infinity],
        output: {
            count: { $sum: 1 }
        }
    }
},
{ $addFields: {
      lowerBound: "$_id",
      upperBound: { $arrayElemAt: [ 
          [0, 10000, 50000, 100000, 1000000, Infinity], 
          { $add: [
              { $indexOfArray: [
                  [0, 10000, 50000, 100000, 1000000, Infinity], "$_id"
              ] }, 
              1
          ] }
      ] }
} }
])

1
太棒了 - 我没有想到只需要使用 addFields。这正如我所预期的那样工作 - 谢谢。 - Matt Andrews
1
如果其中一个桶是空的怎么办?该桶将在桶管道中被跳过,它将不匹配原始桶列表。 - Arjav Dave
@ArjavDave 感谢您的评论!我真的很喜欢批判性思维,而不是盲目地复制粘贴。$indexOfArray运算符在最后一个数组中搜索桶的$_id,以找到前一个边界数组中元素的索引,以便$arrayElementAt选择正确的值。如果您能证明它是错误的,我很乐意审查答案。 - Alex Blex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接