首页 文章

Mongoose过期数据但保留在数据库中

提问于
浏览
2

我目前通过mongoose架构保存数据并从数据库过期,如下所示:

var UserSchema = new Schema({
    createdAt: { type: Date, expires: '1m' },
    name: String,
    email: String
});

唯一的问题是保存到数据库的文档已从数据库中完全删除 . 我将如何重构上述内容,以便名称/电子邮件地址保留在数据库中,但如果用户在到期日后尝试登录,则会收到一条消息“会话已过期,续订会话” . (或类似的东西)

我想这样做,因为如果用户使用过期的电子邮件地址登录,服务器仍然能够查找电子邮件地址并吐出“过期的会话”消息,而不是“未找到”错误,这是删除数据时会发生什么 .

重申一下,如何将过期数据保存在mongo / mongoose数据库中,以便应用程序能够找到用户尝试登录的电子邮件地址,但如果他们的会话已过期,他们需要续订会话吗?

2 回答

  • 5

    你应该使用 Schema Reference 的概念 . 将 expired 字段保存在另一个表中并加入主 user_tableexpire_table (例如名称)

    var UserSchema = new Schema({
        name: String,
        email: String
    });
    
    //save date by-default
    //expire in 1 min as in your example
    var expireSchema = new Schema({
        createdAt: { type: Date, default: Date.now, expires: '1m'  },
        user_pk: { type: Schema.Types.ObjectId, ref: 'user_expire'}
    });
    
    var userTable = mongoose.model('user_expire', UserSchema);
    var expireTable = mongoose.model('expireMe', expireSchema);
    
    //Save new user
    var newUser =  new userTable({
        name: 'my_name',
        email: 'my_email'
    });
    
    newUser.save(function(err, result) {
        console.log(result, 'saved')
        var newExpire =  new expireTable({
            user_pk:result._id
        });
        //use _id of new user and save it to expire table
        newExpire.save(function(err, result) {
            console.log('saved relation')
        })
    })
    

    Now to detect whether session has expired or not

    1. on executing this code before data gets expired

    expireTable.findOne()
    .populate('user_pk')
    .exec(function (err, result) {
        if (err) throw err;
        console.log(result)
        if(result == null) {
            console.log('session has expired, renew session')
        } else {
            console.log('session is active')
        }
    });
    
    //output - session is active
    

    2. on executing this code after data gets expired

    expireTable.findOne()
    .populate('user_pk')
    .exec(function (err, result) {
        if (err) throw err;
        console.log(result)
        if(result == null) {
            console.log('session has expired, renew session')
        } else {
            console.log('session is active')
        }
    });
    
    //output - session has expired, renew session
    
  • 0

    接受的答案很好,但是对于Mongo 3.0及以上版本,

    createdAt: { type: Date, default: Date.now, expires: '1m'  }
    

    不适合我 .

    相反,我用过

    var expireSchema = new Schema({
        expireAt: {
            type: Date,
            required: true,
            default: function() {
                // 60 seconds from now
                return new Date(Date.now() + 60000);
            }
        },
        user_pk: { type: Schema.Types.ObjectId, ref: 'user_expire'}
    });
    

    更多信息在这里:Custom expiry times for mongoose documents in node js

    EDIT

    我上面的评论还需要直接调用Mongo函数,而不是通过Mongoose语法 . 这将是这样的:

    db.[collection-name].createIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } )
    

    此外,这是用于执行ttl字段的方式的Expire Documents at a Specific Clock Time .

    我仍然无法让它工作,但可能是因为ttl收割机运行的不稳定方式(每60秒一次,但可能更长......)

    EDIT

    我的问题是由于早期错误配置的ttl索引持久存在于 expireAt 字段上,这阻止了我以后(正确定义的)索引的工作 . 我修复此问题只是删除任何非_id早期索引,然后在 expireAt 字段上重新添加我的ttl索引 .

    使用 db.[collection-name].getIndexes()

    db.[collection-name].dropIndex({ "expireAt":1 }) 在重新申请之前清除 .

    另外另一个警告 - 在 expiredAt 字段的默认属性中设置日期快照意味着默认值将始终是固定日期 - 而是在每次创建 expireSchema 的实例时动态设置此日期值:

    var expireSchema = new Schema({
        expireAt: Date,
        user_pk: { type: Schema.Types.ObjectId, ref: 'user_expire' }
    });
    
    expireSchema
      .virtual('expiryTime')
      .get(function() {
        //allow for reaper running at 60 second intervals to cause expireAt.fromNow message to be 'in the past'
        var expiryTime = moment(this.expireAt).fromNow();
        if(String(expiryTime).indexOf("ago")){
          expiryTime = "in a few seconds";
        }
        return expiryTime;
      });
    
    var expireModel =  mongoose.model('UserExpire', expireSchema);
    
    expireModel.collection.ensureIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } );
    

相关问题