【问题标题】:mongodb / mongoose subdocument aggregation querymongodb / mongoose 子文档聚合查询
【发布时间】:2020-08-02 18:42:26
【问题描述】:

我需要使用 mongoose 聚合框架从我的架构中获取此输出

我的架构

const innerSchema = mongoose.Schema({
  responseTime: Number,
  day: String,
  hour: Number
})

let logsSchema = mongoose.Schema({
  name: { type: String, enum: ['visit', 'new-request', 'new-customer'] },
  series: { type: [innerSchema], default: [] }
})

我需要的输出如下

        [{
            "name":"visit",
            "series": [
                {
                    "day": "Saturday",
                    "count": 50
                },
                {
                    "day": "Friday",
                    "count": 20
                }
            ]
         },
         {
            "name":"new-request",
            "series": [
                {
                    "day": "Saturday",
                    "count": 100
                },
                {
                    "day": "Friday",
                    "count": 4
                }
            ]
         }]

目前卡在这个聚合查询中

  Logs.aggregate([
    {
      $group: {
        '_id': '$name',
        series: { $first: '$series' }
      }
    },
    { $unwind: '$series' },
    {
      "$group": {
        "_id": '$series.day',
        count: { $sum: 1 }
      }
    },
    { $limit: 7 }

  ])

输出以下内容:

[
    {
        "_id": "Saterday",
        "count": 1
    },
    {
        "_id": "Friday",
        "count": 1
    },
    {
        "_id": "Sunday",
        "count": 5
    }
]

它错过了名称和系列字段

我需要将系列数组限制为前 7 个文档才能获得一周的数据

感谢任何帮助

新 ---> 更新

这是原始数据集

将其更新为简单的结构

      [
    {
        "_id": "5ea1770c165ece5a40af06ea",
        "name": "new-request",
        "day": "Saturday",
        "hour": 14,
        "createdAt": "2020-04-23T11:07:56.175Z",
        "updatedAt": "2020-04-23T11:07:56.175Z",
        "__v": 0
    },
    {
        "_id": "5ea17770165ece5a40af06eb",
        "name": "new-request",
        "day": "Thursday",
        "hour": 14,
        "createdAt": "2020-04-23T11:09:36.364Z",
        "updatedAt": "2020-04-23T11:09:36.364Z",
        "__v": 0
    },
    {
        "_id": "5ea17770165ece5a40af06ec",
        "name": "new-customer",
        "day": "Thursday",
        "hour": 14,
        "createdAt": "2020-04-23T11:09:36.984Z",
        "updatedAt": "2020-04-23T11:09:36.984Z",
        "__v": 0
    },
    {
        "_id": "5ea17771165ece5a40af06ed",
        "name": "visit",
        "day": "Thursday",
        "hour": 14,
        "createdAt": "2020-04-23T11:09:37.603Z",
        "updatedAt": "2020-04-23T11:09:37.603Z",
        "__v": 0
    },
    {
        "_id": "5ea17772165ece5a40af06ee",
        "name": "visit",
        "day": "Thursday",
        "hour": 14,
        "createdAt": "2020-04-23T11:09:38.207Z",
        "updatedAt": "2020-04-23T11:09:38.207Z",
        "__v": 0
    },
    {
        "_id": "5ea17772165ece5a40af06ef",
        "name": "visit",
        "day": "Saturday",
        "hour": 14,
        "createdAt": "2020-04-23T11:09:38.698Z",
        "updatedAt": "2020-04-23T11:09:38.698Z",
        "__v": 0
    },
    {
        "_id": "5ea17773165ece5a40af06f0",
        "name": "visit",
        "day": "Thursday",
        "hour": 14,
        "createdAt": "2020-04-23T11:09:39.247Z",
        "updatedAt": "2020-04-23T11:09:39.247Z",
        "__v": 0
    },
    {
        "_id": "5ea2dd44030d853950379007",
        "name": "visit",
        "day": "Friday",
        "hour": 15,
        "createdAt": "2020-04-24T12:36:20.867Z",
        "updatedAt": "2020-04-24T12:36:20.867Z",
        "__v": 0
    },
    {
        "_id": "5ea2dd56030d853950379008",
        "name": "visit",
        "day": "Friday",
        "hour": 15,
        "createdAt": "2020-04-24T12:36:38.297Z",
        "updatedAt": "2020-04-24T12:36:38.297Z",
        "__v": 0
    },
    {
        "_id": "5ea2dd58030d853950379009",
        "name": "visit",
        "day": "Friday",
        "hour": 15,
        "createdAt": "2020-04-17T00:36:40.583Z",
        "updatedAt": "2020-04-24T12:36:40.583Z",
        "__v": 0
    },
    {
        "_id": "5ea2dd58030d85395037900a",
        "name": "visit",
        "day": "Friday",
        "hour": 15,
        "createdAt": "2020-04-24T12:36:40.878Z",
        "updatedAt": "2020-04-24T12:36:40.878Z",
        "__v": 0
    }
]

在@AlexZeDim 和一些调整的帮助下,我设法让它工作,但我遇到了数据排序的最后一个问题 我需要按 createdAt

对数据进行排序
Logs.aggregate([
    {
      $group: {
        _id: '$name',
        series: { "$push": "$$ROOT" }
      }
    },
    {
      $unwind: "$series"
    },
    {
      $addFields: {
        createdAt: '$series.createdAt'
      }
    },

    { $match: { createdAt: { $gt: lastWeekDate, $lt: date } } },
    {
      $group: {
        _id: {
          name: "$_id",
          day: "$series.day"
        },
        count: {
          $sum: 1
        }
      }
    },

    {
      $group: {
        _id: "$_id.name",
        series: {
          $addToSet: {
            name: "$_id.day",
            value: {
              $sum: "$count"
            }
          }
        },

      }
    },
    {
      $addFields: {
        createdAt: '$createdAt'
      }
    },

    {
      $project: {
        _id: 0,
        name: "$_id",
        series: "$series"
      }
    }
  ])

问题已解决

【问题讨论】:

  • 请提供集合中的原始示例/数据集
  • 另外,我不确定.limit 部分。如果您的series.day 字段具有当前 DayOfTheWeek 的值,那么简单的小组阶段将为您提供所需的一切,因为一周中有 7 个不同的日子。当您limit(7) 时,您只显示最后 7 个值,而不是一周中的 7 个不同的日子。
  • 您可以尝试在 first $group 阶段使用$push 运算符而不是 $first。第一阶段小组赛结束后查看结果。
  • 受限于我需要过去 7 天的数据而不是所有天的数据,我还添加了原始数据集,感谢@AlexZeDim 的回复
  • 将 $first 更改为 $push 没有帮助 @prasad_

标签: node.js mongodb mongoose aggregation-framework


【解决方案1】:

在原始数据集中:不是“星期六”,而是«星期六»。 如果您真的想要/需要{ $limit: 7 } 阶段,您可以随时在此查询的末尾添加它,它会提供您需要的内容:

db.collection.aggregate([
  {
    $unwind: "$series"
  },
  {
    $group: {
      _id: {
        name: "$_id",
        day: "$series.day"
      },
      count: {
        $sum: 1
      }
    }
  },
  {
    $group: {
      _id: "$_id.name",
      series: {
        $addToSet: {
          day: "$_id.day",
          count: {
            $sum: "$count"
          }
        }
      }
    }
  },
  {
    $project: {
      _id: 0,
      name: "$_id",
      series: "$series"
    }
  }
])

MongoPlayground

【讨论】:

  • 酷我感谢你的帮助,但我想我应该在系列记录中添加一个 createdAt 字段? ,我也使用猫鼬,并在名称字段中投射 doc _id,再次感谢
  • 好吧,如果你愿意,你可以删除$project 阶段,你将拥有_id: 用于visits/new_requests 值而不是name 至于在你的架构中使用timestamps: true,这是个好主意,但请记住 mongo 存储日期的方式。如果是这样,您可以每次将date 字段转换为特殊的operators,如$dayOfTheWeek(或类似的东西),以接收当天。
  • 另外,如果我可以获得一周的数据,如果有 2 天没有访问返回计数 0 而不是根本不显示它
  • 如果你想删除count: 0字段,那么你需要使用$cond操作符,对于count: {$eq: 0}
  • 感谢您为我指出正确的方向,我已经设法解决了这个问题:D
猜你喜欢
  • 2021-07-04
  • 2015-05-29
  • 2023-03-30
  • 1970-01-01
  • 2020-07-15
  • 2015-04-27
  • 2017-10-01
  • 2018-04-05
  • 2020-12-05
相关资源
最近更新 更多