首页 > 解决方案 > Mongoose 按日期和值聚合

问题描述

我无法解决我在项目中遇到的问题。

首先,我有一个名为 Emotions 的 Schema,如下所示:

import mongoose from 'mongoose';

const EmotionSchema = new mongoose.Schema({
  classification: {
    type: String,
    required: true,
  },
  probability: {
    type: Number,
    required: true,
  },
  user: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User',
  }
}, {
  timestamps: true,
});

export default mongoose.model('Emotion', EmotionSchema);

还有一些数据是这样的:

[
  {
    "_id": "61144a393c532f066725bd24",
    "classification": "Feliz",
    "probability": 0.98,
    "user": "60eecfeba0810013e750cdbc",
    "createdAt": "2021-08-11T22:07:53.331Z",
    "updatedAt": "2021-08-11T22:07:53.331Z",
    "__v": 0
  },
  {
    "_id": "61144a46d30bd006fa2be702",
    "classification": "Feliz",
    "probability": 0.98,
    "user": "60eecfeba0810013e750cdbc",
    "createdAt": "2021-08-11T22:08:06.618Z",
    "updatedAt": "2021-08-11T22:08:06.618Z",
    "__v": 0
  },
  {
    "_id": "611541dd62a7f214afab3ceb",
    "classification": "Triste",
    "probability": 0.9,
    "user": "60eecfeba0810013e750cdbc",
    "createdAt": "2021-08-12T15:44:29.150Z",
    "updatedAt": "2021-08-12T15:44:29.150Z",
    "__v": 0
  },
  {
    "_id": "611541f762a7f214afab3cf5",
    "classification": "Raiva",
    "probability": 0.86,
    "user": "60eecfeba0810013e750cdbc",
    "createdAt": "2021-08-12T15:44:55.909Z",
    "updatedAt": "2021-08-12T15:44:55.909Z",
    "__v": 0
  },
  {
    "_id": "6115420362a7f214afab3cf7",
    "classification": "Neutro",
    "probability": 0.99,
    "user": "60eecfeba0810013e750cdbc",
    "createdAt": "2021-08-12T15:45:07.297Z",
    "updatedAt": "2021-08-12T15:45:07.297Z",
    "__v": 0
  },
  {
    "_id": "6115420462a7f214afab3cf9",
    "classification": "Neutro",
    "probability": 0.99,
    "user": "60eecfeba0810013e750cdbc",
    "createdAt": "2021-08-12T15:45:08.002Z",
    "updatedAt": "2021-08-12T15:45:08.002Z",
    "__v": 0
  },
  {
    "_id": "611543d252be9a187c380e5d",
    "classification": "Feliz",
    "probability": 0.91,
    "user": "60eecfeba0810013e750cdbc",
    "createdAt": "2021-08-12T15:52:50.599Z",
    "updatedAt": "2021-08-12T15:52:50.599Z",
    "__v": 0
  }
]

我想要的是:

首先按天对这些记录进行分组。之后,按分类计算值,但将这些分类分开。

像这样的东西:

[
  {
    "_id": "12/08/2021",
    "feliz": 1,
    "triste": 1,
    "raiva": 1,
    "neutro": 2,
    "surpreso": 0,

  },
  {
    "_id": "11/08/2021",
    "feliz": 2,
    "triste": 0,
    "raiva": 0,
    "neutro": 0,
    "surpreso": 0,
  }
]

我做了类似的事情,但它只适用于一个价值,例如“Feliz”。在代码中:

Emotion.aggregate([
      { $match: 
        {
          user: user._id,
          classification: "Feliz"
        }
      },
      { $group: {
        _id : { $dateToString: { format: "%d/%m/%Y", date: "$createdAt" } },
        feliz: { $sum: 1 }
      }},
    ], function(err, results) {
      if (err) throw err;
      return res.json(results);
    })

它返回:

[
  {
    "_id": "12/08/2021",
    "feliz": 1
  },
  {
    "_id": "11/08/2021",
    "feliz": 4
  }
]

还有一个问题:从客户端,我总是得到“分类”的值,例如:“Feliz”、“Triste”、“Surpreso”、“Raiva”、“Neutro”。那么在我的模式“Emotion”中添加一个枚举会更好吗?

(对不起我的英语,希望你能理解)。

标签: node.jsmongooseaggregation-framework

解决方案


  • $groupcreatedAt日期和classification,计数总和
  • $groupby only 和 构造键值对中的andcreatedAt的数组classificationcount
  • $arrayToObject将上述对象的键值对数组转换为对象格式
Emotion.aggregate([
  { 
    $match: {
      user: user._id,
      classification: "Feliz"
    }
  },
  {
    $group: {
      _id: {
        createdAt: {
          $dateToString: {
            format: "%d/%m/%Y",
            date: "$createdAt"
          }
        },
        classification: "$classification"
      },
      count: { $sum: 1 }
    }
  },
  {
    $group: {
      _id: "$_id.createdAt",
      classifications: {
        $push: {
          k: "$_id.classification",
          v: "$count"
        }
      }
    }
  },
  {
    $addFields: {
      classifications: {
        $arrayToObject: "$classifications"
      }
    }
  }
], 
function(err, results) {
  if (err) throw err;
  return res.json(results);
})

操场

注意:当计数为 0 时,这不会返回分类!你需要在js中查询后执行此操作。


还有一个问题:从客户端,我总是得到“分类”的值,例如:“Feliz”、“Triste”、“Surpreso”、“Raiva”、“Neutro”。那么在我的模式“Emotion”中添加一个枚举会更好吗?

这取决于您的项目要求,您可以在枚举中设置这些值以限制输入。


推荐阅读