Nodejs中mongodb如何实现按日期分类

Nodejs中mongodb如何实现按日期分类

比如一个博客系统文章有日期属性 数据库里是的日期是 ISODate(“2013-12-30T16:00:00.000Z”) 想按照日期统计每天的文章数量. 请教一下问题: 1.应该用什么方法来实现 2.怎样解决数据库里时差的问题(我要统计当天的文章数,得按照本地时间来统计.)

6 回复

Node.js 中 MongoDB 如何实现按日期分类

假设你有一个博客系统,其中每篇文章都有一个日期属性。数据库中的日期格式是 ISODate("2013-12-30T16:00:00.000Z")。你想按照日期统计每天的文章数量。

1. 实现方法

为了实现这一功能,你可以使用 MongoDB 的聚合管道(aggregation pipeline)来对文章进行分组,并按日期进行统计。以下是具体步骤:

  1. 提取日期:首先,你需要从 ISODate 中提取出年、月、日。
  2. 分组统计:然后,使用 $group 操作符按提取后的日期进行分组,并计算每组的文章数量。

示例代码

const mongoose = require('mongoose');
const { Schema } = mongoose;

// 假设你已经定义了 Article 模型
const articleSchema = new Schema({
  title: String,
  content: String,
  date: Date
});

const Article = mongoose.model('Article', articleSchema);

async function getDailyPostCount() {
  try {
    // 使用聚合管道提取年、月、日并按天分组统计
    const result = await Article.aggregate([
      {
        $project: {
          year: { $year: "$date" },
          month: { $month: "$date" },
          day: { $dayOfMonth: "$date" }
        }
      },
      {
        $group: {
          _id: { year: "$year", month: "$month", day: "$day" },
          count: { $sum: 1 }
        }
      },
      {
        $sort: { "_id.year": 1, "_id.month": 1, "_id.day": 1 }
      }
    ]);

    console.log(result);
  } catch (error) {
    console.error(error);
  }
}

getDailyPostCount();

2. 解决时差问题

MongoDB 存储的日期是 UTC 时间。如果你想根据本地时间进行统计,可以使用 JavaScript 的 moment-timezone 库来处理时区转换。

const moment = require('moment-timezone');

async function getDailyPostCountLocalTime() {
  try {
    const localDate = moment.utc().tz('Asia/Shanghai').format('YYYY-MM-DD');
    const result = await Article.aggregate([
      {
        $match: {
          date: {
            $gte: moment(localDate).startOf('day').toDate(),
            $lt: moment(localDate).endOf('day').toDate()
          }
        }
      },
      {
        $count: "total"
      }
    ]);

    console.log(result[0] ? result[0].total : 0);
  } catch (error) {
    console.error(error);
  }
}

getDailyPostCountLocalTime();

在这个例子中,我们使用 moment-timezone 库将 UTC 时间转换为上海时区的时间,并按本地时间进行统计。

通过上述方法,你可以轻松地在 Node.js 中使用 MongoDB 来按日期分类统计文章数量,并解决时差问题。


  1. 用 mapreduce
  2. mongodb 只支持 UTC 时间

发文章的时候,就备个字段去 $inc,就别单独统计了。 比如: stat 表: {_id:20140101,article:5,reply:10,…} 以后查的时候,多省事,直接用_id 就行了。完全不用计算。

你应该多加个数值字段, 放置本数据加入时距离默认起始时间的毫秒数,或者到比如2014年1月1日距离的毫秒数。

这样只需要加个索引,比较今天距离参考时间的毫秒数。 虽然增加了磁盘容量,不过查询性能肯定是大幅提升的。

范围内容筛选,最好尽量使用数值,不要用字符串或者其他数据类型。

日期字段可以使用$gt $lt去比较的,至于时差的话,mongodb里面是UTC时间,和北京时间差八小时

要实现按日期分类并统计每天的文章数量,可以使用MongoDB的聚合框架。以下是一个示例代码,展示如何在Node.js中实现这一功能。

示例代码

const mongoose = require('mongoose');
const Article = mongoose.model('Article', new mongoose.Schema({
    title: String,
    content: String,
    createdAt: { type: Date, default: Date.now }
}));

async function getArticlesByDate() {
    try {
        // 获取本地时间的日期部分(不包含时间)
        const localDate = new Date();
        const localDateString = `${localDate.getFullYear()}-${String(localDate.getMonth() + 1).padStart(2, '0')}-${String(localDate.getDate()).padStart(2, '0')}`;

        // 转换为ISO日期格式
        const startOfDay = new Date(`${localDateString}T00:00:00.000Z`);
        const endOfDay = new Date(`${localDateString}T23:59:59.999Z`);

        // 使用聚合框架查询
        const result = await Article.aggregate([
            {
                $match: {
                    createdAt: {
                        $gte: startOfDay,
                        $lt: endOfDay
                    }
                }
            },
            {
                $group: {
                    _id: { $dateToString: { format: "%Y-%m-%d", date: "$createdAt" } },
                    count: { $sum: 1 }
                }
            }
        ]);

        console.log(result);
    } catch (error) {
        console.error(error);
    }
}

// 运行函数
getArticlesByDate();

解释

  1. 获取本地日期

    • new Date() 创建一个新的JavaScript日期对象。
    • getFullYear()getMonth()getDate() 方法分别获取年份、月份和日期。
    • padStart(2, '0') 确保月份和日期始终是两位数。
  2. 创建日期范围

    • $gte$lt 分别表示大于等于和小于,用于限定查询的时间范围。
    • startOfDayendOfDay 分别表示当天的开始时间和结束时间。
  3. 聚合框架

    • $match 阶段用于过滤出符合时间范围的文档。
    • $group 阶段按日期分组,并计算每组中的文档数量。
  4. 处理时差问题

    • 通过将时间转换为本地日期,我们确保了统计的是本地时间范围内的数据。

这样就可以按日期统计每天的文章数量了。

回到顶部