我有一个与mongoDb实例集成的基于节点的后端。 DB具有日历事件的集合,每个日历事件都有一个唯一的日期时间字段。我正在尝试考虑在设置时间前15分钟执行提醒功能的最佳方法。
我想出的唯一想法是用setInterval一致地查询数据库,然后运行该函数。有更好的方法吗?
答案 0 :(得分:0)
从数据库轮询是最简单的方法。如果您担心避免过于频繁地查询数据库,则可以尝试以下操作。
如果您的事件已更新,则可以使用MongoDB的Change Streams来监视更改。日历事件更新后,将其与下一个提醒事件进行比较,如果它在下一个日历提醒之前,则替换下一个提醒。
希望这会有所帮助。
答案 1 :(得分:0)
显然setInterval
并提取数据库似乎是最简单的方法。下面的解决方案可以认为是数据库启动那些计划的事件的替代方法,因此您将获得 push 而不是pull方法。
假设您有一个简单的集合 scheduledEvents ,其中包含一个类型为 ISODate 的字段 scheduledAt ,例如:
{ "_id" : ObjectId("5c457cb554651d56ffe0c759"), "scheduledAt" : ISODate("2019-01-21T08:03:01.129Z") }
然后,您可以在该集合上创建TTL index。基本上的想法是,当 scheduledAt 成为过去的日期时,MongoDB数据库服务器将定期删除这些文档。
db.scheduledEvents.createIndex( { "scheduledAt": 1 }, { expireAfterSeconds: 30} )
在幕后,有一个计划的作业正在数据库服务器上运行,该作业将查询并删除所有这些文档。这些文档不会立即被删除-稍有延迟,但是您可以接受。
现在,您有了一种调度机制,因此您所需要做的就是从代码中订阅这些事件。为此,您可以利用Change Streams。
要使用它们,您必须将数据库作为副本集运行(可以为standalone replica set)。然后,在您的应用程序代码中,您可以使用以下代码预订 scheduledEvents 集合:
const changeStreamCursor = db.scheduledEvents.watch();
function pollStream(cursor) {
while (!cursor.isExhausted()) {
if (cursor.hasNext()) {
var change = cursor.next();
if(change.operationType === "delete"){
// your logic goes here
}
}
}
pollStream(cursor);
}
pollStream(changeStreamCursor);
很显然,scheduledEvents
集合可以包含与您的业务逻辑相关的其他字段,并且可以在变更流侦听器中访问这些字段。