node.js - 如何使用日期字段按周、小时和天过滤文档

标签 node.js mongodb express mongoose

我是 express 和 mongoDB 的初学者。我正在执行一项任务,其中我有一个称为销售类型的模型 -

{
    userName : String,
    amount   : Number,
    date     : Date
}

现在我必须创建一个 API,它应该有 3 种类型的参数之一 - “每日”、“每周”、“每月”。 如果参数是

每天 - 然后我必须根据一天中的每个小时从销售表发送统计数据(金额总和)。

每周 - 然后我必须根据一周中的每一天发送统计数据

每月 - 然后我必须在每个月的每一天发送统计数据

在思考了一些逻辑之后,我想出了这个 -

我能够进行每日统计,但它看起来也很复杂

app.get("/fetchSales/:id",async (req, res)=>{
    const { id } = req.params;
    const allSales = await sales.find({});
    const dates = [];
    for(i in allSales){
        let date = allSales[i].date.toISOString().replace('Z', '').replace('T', ''); 
        const dateFormat = dayjs(date);
        dateFormat.amount = allSales[i].amount;
        dates.push(dateFormat);
    }
    if(id === "daily") {
        const stats = {};
        for(let hour = 0; hour < 24; hour++) {
            let sum = 0
           for (x in dates) {
               if (dates[x]["$H"] === hour)  sum += dates[x].amount
           }
           stats[hour] = sum;
        }
        res.send(stats);
    }
})

但接下来我必须使用多个循环,而且看起来不太好。我读到聚合查询可能对我有帮助。

结构天js给我的是——

  d {
    '$L': 'en',
    '$d': 2021-01-13T13:00:00.000Z,
    '$x': {},
    '$y': 2021,
    '$M': 0,
    '$D': 13,
    '$W': 3,
    '$H': 18,
    '$m': 30,
    '$s': 0,
    '$ms': 0,
    amount: 1700 //added on my own//
  }

我想要的一些输出结构——每天

{
 0: 0$,
 1: 0$,
 2: 24$,
 ...
 23: 2$
}

知道我该如何处理吗?

最佳答案

您可以根据输入构建查询条件,但让 Mongodb 完成繁重的工作:

app.get("/fetchSales/:id", async (req, res) => {
    const {id} = req.params;

    const groupCondition = {
        sum: {$sum: 1}
    };

    if (id === 'monthly') {
        groupCondition._id = {$week: '$date'};
    } else if (id === 'weekly') {
        groupCondition._id = {$dayOfMonth: '$date'};
    } else if (id === 'weekly') {
        groupCondition._id = {$hour: '$date'};
    } else {
        // can this happen? what to do here.
    }

    const allSales = await sales.aggregate([
        {
            $group: groupCondition
        },
        {
            $sort: {
                _id: 1
            }
        }
    ]);
});

请注意,这不会返回文档数为 0 的天/周/小时,您必须通过管道或代码手动插入它们。

对于每个完整日期而不是每个特定的一般小时/天的实际 $group,您应该使用此:

app.get("/fetchSales/:id", async (req, res) => {
    const {id} = req.params;

    const groupCondition = {
        _id: {year: {$year: '$date'}, $month: {'$month': "$date"}, week: {'$week': "$date"} },
        sum: {$sum: 1},
        date: {$first: '$date'} //for sorting
    };

    switch (id) {
        case 'weekly':
            groupCondition._id.$dayOfMonth = {$dayOfMonth: '$date'};
        case 'daily':
            groupCondition._id.$hour = {$hour: '$date'};
    }

    const allSales = await sales.aggregate([
        {
            $group: groupCondition
        },
        {
            $sort: {
                date: 1
            }
        },
        {
            $project: {
                _id: 1,
                sum: 1
            }
        }
    ]);
});

这将为您提供以下结构的文档:

[
    {
        _id: { year: 2020, month: 5, week: 13, day: 22, hour: 5},
         sum: 50
    }
]

关于node.js - 如何使用日期字段按周、小时和天过滤文档,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67149353/

相关文章:

python - 如何使用 Python 从 MongoDB 中的此文档中删除值

node.js - 有没有办法在维护数据的同时更改 mongoDB 结构(从嵌套/嵌入文档到对象引用列表)?

node.js - 如何从 typeorm postgreSQL 中获取软删除的实体?

node.js - 为什么构建目录隐藏在 Netbeans 8.2 Node.js 应用程序的项目 View 中

javascript - 动态获取模型的外键列名

node.js - 直接从 URL 查询字符串提供的 mongo 查询有多危险?

node.js - Node http-proxy 和 express

node.js - 使用express删除 Mongoose 条目

node.js - Mongoose findByIdAndUpdate upsert 在初始插入时返回空文档

javascript - Node.js Socketio 和动态内容