【问题标题】:Mongoose aggregate by date and valuesMongoose 按日期和值聚合
【发布时间】:2021-10-16 00:50:06
【问题描述】:

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

首先,我有一个名为 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.js mongoose aggregation-framework


    【解决方案1】:
    • $group by createdAt 日期和classification,计数总和
    • $group by createdAt only 并在键值对中构造 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);
    })
    

    Playground

    注意: count 为 0 时不会返回分类!需要在js中查询后进行。


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

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

    【讨论】:

    • 非常感谢!你回答的正是我想要的,我理解代码中所做的一切。关于枚举,我可能会使用它。
    • 但是你展示的方式,所有的Emotions值都被组合在一起了。要仅过滤用户为 req.user._id 的情绪,我会在聚合开始时进行匹配吗?如帖子所示。
    • 是的,您可以按原样进行比赛阶段,我在回答时错过了它,只关注主要问题。
    猜你喜欢
    • 2017-10-07
    • 2015-06-28
    • 2016-06-09
    • 2014-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多