【问题标题】:Mongodb aggregate $group for non-existing itemsMongodb 为不存在的项目聚合 $group
【发布时间】:2020-02-12 05:37:46
【问题描述】:

我有这样的文件:

文件:

{score: 1, value: 10}
{score: 3, value: 10}
{score: 1, value: 10}
{score: 4, value: 10}
{score: 1, value: 10}
{score: 5, value: 10}
{score: 5, value: 10}
{score: 10, value: 10}

在这个集合中,没有 2、6、7、8、9 的分数,但我需要如下输出。

输出:

{score: 1, avg: 10}
{score: 2, avg: 0}
{score: 3, avg: 10}
{score: 4, avg: 10}
{score: 5, avg: 10}
{score: 6, avg: 0}
{score: 7, avg: 0}
{score: 8, avg: 0}
{score: 9, avg: 0}
{score: 10, avg: 10}

Mongo 聚合中的任何选项都会生成这个。请帮忙

【问题讨论】:

  • 你怎么知道没有分数:2,6,7,8,9。您是否事先知道score 的项目范围从 1 到 10?
  • 你的 mongo 版本是什么?

标签: mongodb mongodb-query aggregation-framework


【解决方案1】:

您可以使用aggregation 进行尝试:

db.collection.aggregate([
    { $group: { _id: '$score', avg: { $avg: '$value' } } },
    { $group: { _id: '', min: { $min: '$_id' }, max: { $max: '$_id' }, data: { $push: '$$ROOT' } } },
    { $project: { _id: 0, data: 1, nums: { $range: ['$min', "$max", 1] } } },
    { $project: { data: { $concatArrays: ["$data", { $map: { input: { $setDifference: ["$nums", "$data._id"] }, in: { _id: '$$this', avg: 0 } } }] } } },
    { $unwind: '$data' }, { $replaceRoot: { newRoot: "$data" } }
])

测试: MongoDB-Playground

【讨论】:

    【解决方案2】:

    假设你知道分数的范围,有一个技巧可以准确地达到你想要的:

    1 - 在您的集合中为每个分数插入一个文档,其中 value 字段未设置或设置为 null :

    db.collection.insertMany([
      {
        score: 1,
      },
      {
        score: 2,
      },
      {
        score: 3,   
      },
      {
        score: 4,    
      },
      {
        score: 5,   
      },
      {
        score: 6,  
      },
      {
        score: 7,    
      },
      {
        score: 8,    
      },
      {
        score: 9, 
      },
      {
        score: 10,
      }
    ]);
    

    不设置value字段很重要,因为设置为0的值会影响平均计算

    当然这个操作只能执行一次。

    然后您可以应用以下聚合,它将准确输出您需要的内容:

    db.collection.aggregate([
      {
        $bucket: {
          groupBy: "$score",
          boundaries: [
            0,
            1,
            2,
            3,
            4,
            5,
            6,
            7,
            8,
            9,
            10,
            11
          ],
          output: {
            avg: {
              $avg: "$value"
            }
          }
        }
      },
      {
        $project: {
          score: "$_id",
          avg: {
            $ifNull: [
              "$avg",
              0
            ]
          },
          _id: 0
        }
      }
    ])
    

    将输出:

    [
      {
        "avg": 10,
        "score": 1
      },
      {
        "avg": 0,
        "score": 2
      },
      {
        "avg": 10,
        "score": 3
      },
      {
        "avg": 10,
        "score": 4
      },
      {
        "avg": 10,
        "score": 5
      },
      {
        "avg": 0,
        "score": 6
      },
      {
        "avg": 0,
        "score": 7
      },
      {
        "avg": 0,
        "score": 8
      },
      {
        "avg": 0,
        "score": 9
      },
      {
        "avg": 10,
        "score": 10
      }
    ]
    

    你可以测试一下here

    【讨论】:

      猜你喜欢
      • 2023-04-11
      • 2016-04-29
      • 2023-03-07
      • 1970-01-01
      • 2019-03-27
      • 1970-01-01
      • 2019-09-03
      • 2021-04-05
      • 2021-06-11
      相关资源
      最近更新 更多