如何限制用户每日发帖限制 (MERN)

时间:2021-03-28 08:22:29

标签: node.js mongodb mongoose passport.js mongodb-atlas

我目前使用通行证进行身份验证,使用 mongodb 来存储用户信息。

然而,我一直试图限制用户的每日发帖限制。我想在 User Schema 中设置一个类似每日发帖限制的字段,每当用户发帖时,我都会扣除计数。

const user = new mongoose.Schema({


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

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

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

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

2 个答案:

答案 0 :(得分:1)

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),这些查询将非常便宜,而且它们很难不同步。

单独的缓存集合

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

答案 1 :(得分:0)

既然你使用的是 MongoDB,我建议,

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