我正在构建一个聊天机器人(使用MeteorJS/NodeJS
),每天与大约2,000个活跃用户互动。我知道每天与机器人聊天的确切人数,因为我将用户的活动信息存储在名为ActiveReports
的MongoDB
集合中。
这是我的应用中的一个场景:如果用户在一天内与机器人聊天100 次(= 100 条消息),将执行以下步骤:
- receive message from users
- check if this user is marked as 'active' today ? // high cost
- if yes => don't do anything
- if no => mark this user as 'active' for today
如您所见,对每条消息执行步骤 2。此步骤在技术上等效于访问 ActiveReports 集合,找到时间戳 = 今天,用户 = 用户 A 的集合。由于ActiveReports
馆藏有很多文档(大约 100,000 个文档),这是一项相当繁重的任务。这会对应用的性能产生负面影响。
注 1:这是ActiveReports
集合架构:
SimpleSchema({
// _id must be set `type` as String and `optional` as true
// to avoid ObjectId(_id) after insert in to database
_id: {
type: String,
optional: true,
},
date: {
type: Date, // Note: date is always the timestamp of the start of the current day, so 1AM timestamp and 9PM timestamp will be changed to 0AM timestamp (before the insert)
},
userId: {
type: String,
},
});
这就是我为这个集合编制索引的方式:
ActiveReports._ensureIndex({ date: 1, userId: 1 }, { unique: true });
注 2:用户在一天内处于活动状态,表示他当天至少与机器人交互 1 次(例如向机器人发送消息)。
任何想法如何改善这一点?如果您需要更多信息,请告诉我。谢谢。
将字段last_active_date
添加到用户架构,并在每次收到消息时更新它。如果日期与今天匹配,您就完成了。如果不是,则需要更新字段并将记录添加到集合ActiveReports
。
实际上,在我看来,您正在尝试以使用关系数据库的方式在这里使用Mongo。我的意思是,如果您只想将用户标记为活动,则无需ActiveReports
。
如果您尝试构建某种报告来显示每个用户每天的应用程序使用情况,则可以在后台执行此操作。你可以有一个每天运行一次的作业(实际上,如果你的用户在不同的时区,并且你想容忍他们的时间,你可能希望每天运行几次)。此作业将查询User
集合,并为找到last_active_date
current_date
的每个用户向ActiveReports
添加记录。
如果您正在构建无状态服务器应用程序,您至少需要做的是拉取用户的记录以检查活动状态。
您可以考虑让守护程序任务处理活动报告并在后台更新用户日期。 这样,您只需处理一次这些记录,用户信息就可以使用了。 此外,该进程可以具有状态,因此更新每个用户每条记录的最佳选择。