计算 MongoDB 中对象值的平均值

Calculate average for object values in MongoDB

我想根据 2021 年的平均评分对这些记录进行降序排序:

[
  {
    "id": 1,
    "slug": "shop 1",
    "stats": {
      "time_stats": {
        "2021": {
          "1": 9.04,
          "2": 8.17,
          "10": 8.46,
          "7": 9.35,
          "11": 8.53,
          "6": 8.35,
          "5": 8.63,
          "9": 9.13,
          "3": 8.9,
          "8": 7.64,
          "4": 8.65,
          "12": 7.45
        },
        
      }
    }
  },
  {
    "id": 2,
    "slug": "shop 2",
    "stats": {
      "time_stats": {
        "2021": {
          "1": 5,
          "10": 9.35,
          "12": 6,
          "11": 8,
          "2": 3,
          "3": 5,
          "9": 4
        },
        
      }
    }
  },
  {
    "id": 3,
    "slug": "shop 3",
    "stats": {
      "time_stats": {
        "2021": {
          "3": 9.57,
          "11": 7.83,
          "4": 8.94,
          "2": 9.1,
          "6": 8.5,
          "5": 9.43,
          "12": 7.93,
          "10": 9.28,
          "9": 9.84,
          "7": 9.38,
          "1": 8.91,
          "8": 9.75
        },
        
      }
    }
  }
]

2021 对象中的每个属性代表一个月。我不知道从哪里开始,Here's what I've tried 到目前为止

db.collection.aggregate([
  {
    $unwind: "$stats"
  },
  {
    $unwind: "$stats.time_stats.2021"
  },
  {
    $group: {
      _id: "$slug",
      yearAvg: {
        $avg: {
          $sum: [
            "$stats.time_stats.2021.1",
            "$stats.time_stats.2021.2",
            "$stats.time_stats.2021.3",
            "$stats.time_stats.2021.4",
            "$stats.time_stats.2021.5",
            "$stats.time_stats.2021.6",
            "$stats.time_stats.2021.7",
            "$stats.time_stats.2021.8",
            "$stats.time_stats.2021.9",
            "$stats.time_stats.2021.10",
            "$stats.time_stats.2021.11",
            "$stats.time_stats.2021.12",
            
          ]
        }
      }
    }
  }
])

但我不确定如何继续实施。非常感谢任何帮助!

首先,您需要一种将 time_stats 散列转换为数组的方法,这将帮助您推导平均值,因为 MongoDB 已经有有用的运算符,例如$avg. The $avg 运算符 在数组操作数上工作以 return 平均值。在你的情况下,你需要一个转换 hashmap

的操作
{
    "1": 9.04,
    "2": 8.17,
    "10": 8.46,
    "7": 9.35,
    "11": 8.53,
    "6": 8.35,
    "5": 8.63,
    "9": 9.13,
    "3": 8.9,
    "8": 7.64,
    "4": 8.65,
    "12": 7.45
}

使用 $objectToArray 运算符到键值对象数组,让我们调用新字段 time_stats_2001_average:

{
    time_stats_2001_average: [
        { "k" : "1", "v" : 9.04 }, 
        { "k" : "2", "v" : 8.17 }, 
        { "k" : "3", "v" : 8.9 }, 
        { "k" : "4", "v" : 8.65 }, 
        { "k" : "5", "v" : 8.63 }, 
        { "k" : "6", "v" : 8.35 }, 
        { "k" : "7", "v" : 9.35 }, 
        { "k" : "8", "v" : 7.64 }, 
        { "k" : "9", "v" : 9.13 }, 
        { "k" : "10", "v" : 8.46 }, 
        { "k" : "11", "v" : 8.53 }, 
        { "k" : "12", "v" : 7.45 }
    ]
}

然后使用表达式计算平均值:

{ time_stats_2001_average: { $avg: '$time_stats_2001_average.v' } }

使用排序运算符在新字段上对生成的文档进行排序:

{ $sort : { time_stats_2001_average : -1 } }

您的完整聚合管道如下所示 (Mongo Playground):

db.collection.aggregate([
    { '$addFields': {
        'time_stats_2001_average': {
            '$avg': {
                '$map': {
                    'input': {
                        '$objectToArray': '$stats.time_stats.2021'
                    },
                    'in': '$$this.v'
                }
            }
        }
    } },
    { '$sort': { 'time_stats_2001_average': -1 }  }
])

使用另一个替代管道 (Mongo Playground):

db.collection.aggregate([
    { '$addFields': {
        'time_stats_2001_average': {
            '$objectToArray': '$stats.time_stats.2021'
        }
    } },
    { '$addFields': {
        'time_stats_2001_average': {
            '$avg': '$time_stats_2001_average.v'
        }
    } },
    { '$sort' : { 'time_stats_2001_average' : -1 } }
])