sql >> データベース >  >> NoSQL >> MongoDB

MongoDB:スケジューラー(cronjob)をエミュレートするためにChange StreamでTTLイベントをキャプチャすることは可能ですか?

    ChangeStreamsとTTLを使用してcronジョブをエミュレートすることができました。私が行ったことを詳細に説明する投稿を公開し、クレジットを付与しました: https://www。 patreon.com/posts/17697287

    ただし、基本的に、ドキュメントの「イベント」をスケジュールする必要があるときはいつでも、ドキュメントを作成するときに、イベントドキュメントも並行して作成します。このイベントドキュメントの_idは、最初のドキュメントと同じIDになります。

    また、このイベントドキュメントではTTLを設定します。

    TTLの有効期限が切れたら、変更ストリームを使用してその「削除」変更をキャプチャします。次に、変更のdocumentKeyを使用して(トリガーするドキュメントと同じIDであるため)、最初のコレクションでターゲットドキュメントを検索し、そのドキュメントで必要な操作を行います。

    ExpressとMongooseでNode.jsを使用して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');
            });
        });
    
    }
    

    そして、これがmodel /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);
    


    1. 2.4 C#MongoドライバーでExplainクエリを実行するにはどうすればよいですか?

    2. bsonドキュメントのバイト単位でサイズを取得する方法

    3. ServiceStackエンティティIDフィールド名

    4. PHPMongoDBは$matchと$groupと$addToSetを集約します