gpt4 book ai didi

MongoDB:是否可以使用 Change Stream 捕获 TTL 事件来模拟调度程序(cronjob)?

转载 作者:行者123 更新时间:2023-12-02 20:28:13 24 4
gpt4 key购买 nike

我是 MongoDB 的新手,我正在寻找一种方法来执行以下操作:

我收集了一些可供使用的可用“东西”。用户可以“保存”一个“事物”并减少可用事物的数量。但他有时间在它到期之前使用它。如果它过期了,这个东西必须回到集合中,再次增加它。

如果有一种方法可以在 Mongo 中监视“过期日期”,那就太理想了。但在我的搜索中,我只找到了一个用于自动删除整个文档的 TTL(生存时间)。

但是,我需要的是过期的“事件”……我想知道是否可以使用 Change Streams 捕获此事件。然后我可以使用该事件再次增加“事物”。

可以吗?或者会有更好的方法来做我想做的事吗?

最佳答案

我能够使用 Change Streams 和 TTL 来模拟 cronjob。我发表了一篇文章,详细解释了我所做的事情,并在以下位置给出了学分: https://www.patreon.com/posts/17697287

但是,基本上,每当我需要为文档安排“事件”时,当我创建文档时,我也会同时创建一个事件文档。该事件文档的 _id 与第一个文档的 ID 相同。

此外,对于此事件文档,我将设置一个 TTL。

当 TTL 到期时,我将使用 Change Streams 捕获其“删除”更改。然后我将使用更改的 documentKey(因为它与我要触发的文档具有相同的 ID)在第一个集合中找到目标文档,并对该文档执行任何我想做的事情。

我将 Node.js 与 Express 和 Mongoose 结合使用来访问 MongoDB。这是要添加到 App.js 中的相关部分:

const { ReplSet } = require('mongodb-topology-manager');

run().catch(error => console.error(error));

async function run() {
console.log(new Date(), 'start');
const bind_ip = 'localhost';
// Starts a 3-node replica set on ports 31000, 31001, 31002, replica set
// name is "rs0".
const replSet = new ReplSet('mongod', [
{ options: { port: 31000, dbpath: `${__dirname}/data/db/31000`, bind_ip } },
{ options: { port: 31001, dbpath: `${__dirname}/data/db/31001`, bind_ip } },
{ options: { port: 31002, dbpath: `${__dirname}/data/db/31002`, bind_ip } }
], { replSet: 'rs0' });

// Initialize the replica set
await replSet.purge();
await replSet.start();
console.log(new Date(), 'Replica set started...');

// Connect to the replica set
const uri = 'mongodb://localhost:31000,localhost:31001,localhost:31002/' + 'test?replicaSet=rs0';
await mongoose.connect(uri);
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function () {
console.log("Connected correctly to server");
});

// To work around "MongoError: cannot open $changeStream for non-existent database: test" for this example
await mongoose.connection.createCollection('test');

// *** we will add our scheduler here *** //

var Item = require('./models/item');
var ItemExpiredEvent = require('./models/scheduledWithin');

let deleteOps = {
$match: {
operationType: "delete"
}
};

ItemExpiredEvent.watch([deleteOps]).
on('change', data => {
// *** treat the event here *** //
console.log(new Date(), data.documentKey);
Item.findById(data.documentKey, function(err, item) {
console.log(item);
});
});

// The TTL set in ItemExpiredEvent will trigger the change stream handler above
console.log(new Date(), 'Inserting item');
Item.create({foo:"foo", bar: "bar"}, function(err, cupom) {
ItemExpiredEvent.create({_id : item._id}, function(err, event) {
if (err) console.log("error: " + err);
console.log('event inserted');
});
});

}

这是模型/ScheduledWithin 的代码:

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var ScheduledWithin = new Schema({
_id: mongoose.Schema.Types.ObjectId,
}, {timestamps: true});
// timestamps: true will automatically create a "createdAt" Date field

ScheduledWithin.index({createdAt: 1}, {expireAfterSeconds: 90});

module.exports = mongoose.model('ScheduledWithin', ScheduledWithin);

关于MongoDB:是否可以使用 Change Stream 捕获 TTL 事件来模拟调度程序(cronjob)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49389459/

24 4 0