【问题标题】:Sails.js expireAfterSeconds option in the modelSails.js 模型中的 expireAfterSeconds 选项
【发布时间】:2026-01-08 23:55:01
【问题描述】:

我正在使用sails 编写一个应该在几个小时后过期的简单模型,所以我需要类似

    createdAt: {
        type: 'Date',
        expires : 60,
        index: true
    }

但是当我检查我的数据库(MongoDB)时,“expireAfterSeconds”似乎不起作用,因此我必须使用

db.collection.ensureIndex( { "createdAt": 1 }, { expireAfterSeconds: 3600 } )

不知道是否可以在模型中设置“过期”选项?

【问题讨论】:

    标签: mongodb model sails.js database


    【解决方案1】:

    检查负责处理index属性属性[1]的sails-mongo源代码,似乎它没有考虑到像expires属性这样的东西。不过这是有道理的,因为sails.js 水线ORM 不支持特定于数据库的功能,例如MongoDB 中的索引数据过期。

    但是,waterline 确实通过Collection.native() 方法[2] 提供了对 MongoDB 本机连接(使用 node-mongodb-native)的访问权限[2]

    很有可能,您只需要在 Sails 应用程序的生命周期中对模型的索引进行一次更改,因此最好的位置是在 config/bootstrap.js 文件中。在sails.js 生命周期的这一点上,所有模型都已实例化,因此您可以执行以下操作来对您的键执行必要的逻辑:

    // config/bootstrap.js
    exports.bootstrap = function (done) {
    
        YourModelName.native(function (err, collection) {
            // define index properties
            collection.ensureIndex( { "createdAt": 1 }, { expireAfterSeconds: 3600 } );
    
            // be sure to call the bootstrap callback to indicate completion
            done();
        });
    }
    

    您可以更进一步,编写一个实用程序来检查sails 已加载的模型(它们可用作全局对象sails.models 中的键),如果它们具有expires 属性,则执行必要的本机功能。这也需要在config/bootstrap.js 中完成。

    如果您有需要在每条记录的基础上完成的本机功能,您可以使用sails.js 模型生命周期挂钩[3]。

    参考:

    【讨论】:

    • 谢谢!真的很好的解决方案!一条评论:需要回调函数来执行ensureIndex操作,否则会引发错误“Cannot use a writeConcern without a provided callback”
    • @Chuan:嗯,好吧。那么如果要防止引导程序在确保索引之前继续进行,那么在传递给 ensureIndex 的回调中调用 done() 将很重要。
    • 在我的情况下,让引导程序继续是保存的,所以我只是把 done() 放在外面。但你是对的,在某些情况下,防止它继续很重要,好点!
    【解决方案2】:

    更新: 我创建了一个sails 挂钩,为使用sails-mongo 适配器的模型提供高级索引选项。

    支持所有 mongo 索引选项。

    https://www.npmjs.com/package/sails-hook-mongoat


    旧:

    如果模型属性具有 expires 属性并且是“日期”类型,我创建了以下自动执行此操作。只需粘贴到您的 config/bootstrap.js

    希望对你有帮助!

      _.forEach(Object.keys(sails.models), function(key) {
        var model = sails.models[key];
        _.forEach(Object.keys(model.attributes), function(attr) {
          if (model.attributes[attr].hasOwnProperty('expires')) {
            var seconds = model.attributes[attr].expires;
            // delete validators from global model, otherwise sails will error
            delete sails.models[key].attributes[attr].expires;
            delete sails.models[key]._validator.validations[attr].expires;
            if (model.attributes[attr].hasOwnProperty('type') && model.attributes[attr].type === 'date') {
              var obj = {};
              obj[attr] = 1;
              model.native(function(err, collection) {
                // define index properties
                collection.ensureIndex(obj, {
                  expireAfterSeconds: seconds
                }, function(err) {
                  if (err)
                    sails.log.error(err);
                  else
                    sails.log.info(key + " model attribute '" + attr + "' has been set to expire the document after " + seconds + " seconds.");
                });
              });
            } else {
              sails.log.warn(key + " model attribute '" + attr + "' is set to expire but is not of type 'date'. Skipping...");
            }
          }
        });
      });

    【讨论】: