如何限制用户每日post限额(MERN)

How to limit users daily post limit (MERN)

我目前正在使用护照进行身份验证并mongodb存储用户信息。

但是我一直试图限制用户的每日 post 限制。我正在考虑在用户模式中有一个像每日 post 限制这样的字段,每当用户 post 我扣除计数。

const user = new mongoose.Schema({


githubId: {
    required: true,
    type: String,
  },

  username: {
    required: true,
    type: String,
  },

  dailyPostLimit: {
    type: Number,
    default: 3,
  },
});

但是我不确定是否有办法每天将该计数重置为默认值 (3)。这里是否适合 CRON 任务,或者是否有更简单的方法来完成此任务?

既然你正在使用 MongoDB 我建议,

  1. 使用 agenda 并创建一个以 UTC 00:00(如果您有来自不同时区的不同用户)或用户所在国家/地区特定时区运行的作业。
  2. 在此作业中,在您的 user 模型上调用 updateMany 函数以重置 dailyPostLimit 字段。

cron 任务可以很好地重置像这样的值,并且缓存像这样的值是解决此问题的合理方法。但是,请记住,您正在缓存此值,而缓存失效是一个 困难 问题,通常会导致错误和额外的复杂性。

计数帖子

我的第一直觉不是缓存,而是每次都计算帖子的数量。这是一些伪代码:

const count = await posts.count({userId, createdAt: {$gte: startOfDay}});
// alternative: const count = await posts.count({userId, _id: {$gte: startofDayConvertedToMongoId});
if (count > 3) throw new Error("no more posts for you");
await posts.create(newPost)

(注意:如果您担心竞争条件,您选择的任何解决方案都需要检查交易中的计数)

如果您有一个以 {userId: 1, createdAt: 1} 开头的索引,或者如果您使用 _id 而不是 {userId: 1, _id: 1}(假设您不允许客户端 _id 创建),这些查询将非常便宜,而且它们很难不同步。

单独缓存collection

即使您决定缓存这些创建值,我也建议将它们缓存在远离用户 collection 的地方,以使您的 collection 更加专注。您可以创建 post_count collection,然后仅更新这些计数的缓存 collection:post_count.updateOne({userId, day}, {$incr: {count: 1}, $setOnInsert: {day, userId, count: 0}}, {upsert: true});。这种方法的一个好处是您可以在 day 上使用 ttl 索引让 mongo 自动删除此 collection 中过期的旧文档。