【问题标题】:Mongo DB document is not deleting after it expiresMongo DB文档过期后不会删除
【发布时间】:2019-10-06 06:54:03
【问题描述】:

我正在尝试设置一个模型,以便在添加表时,它将有一个到期日期,在它到期后,该表将自行删除。我尝试这样实现它:

expires: '1m'

expires: 10

我有一个如下设置的表:

const verifySchema = new mongoose.Schema({
    _userId: {
        type: mongoose.Schema.Types.ObjectId,
        required: true,
        ref: 'User'
    },
    hash: { type: String, required: true },
    createdAt: { type: Date, required: true, default: Date.now, expires: '1m' }
});

问题是,一分钟后什么都没有发生。它不会在数据库中被删除。我做错了什么吗?

如何在一分钟后删除表?

【问题讨论】:

  • 我不确定1m 速记是否有效。尝试将 1 分钟(以秒为单位)设置为 expires: 60
  • 也看看这个问题/答案:stackoverflow.com/q/14597241/1861779
  • 注意:您可能需要在更改expires 属性之前删除索引:docs.mongodb.com/manual/core/index-ttl/#restrictions
  • 删除您的索引并重新创建它。代码看起来不错。 expires: '1m' 有效,但请记住 TTL 进程每 60 秒运行一次,因此它并不总是完全准时。我刚刚对其进行了测试,它可以与2m 等一起按预期工作。
  • @t.888 你能解释一下删除索引是什么意思吗?另外,我没有更改 expire 属性。它是任何默认值,我从不更改它。我应该改变它吗?

标签: node.js mongodb express mongoose


【解决方案1】:

这是一个使用 mongoose v5.5.9 的工作示例。原来缺少的部分是 createdAt 字段中的架构条目 index: { expires: '1m' }

const mongoose = require('mongoose')
// $ npm install uuid
const uuid = require('uuid')

const ObjectId = mongoose.Types.ObjectId

// Avoid deprecation warnings
mongoose.set('useNewUrlParser', true);
mongoose.set('useFindAndModify', false);
mongoose.set('useCreateIndex', true);

// Create the schema.
const verifySchema = new mongoose.Schema({
  _userId: {
      type: ObjectId,
      required: true,
      ref: 'User'
  },

  hash: { type: String, required: true },

  createdAt: {
    type: Date,
    required: true,
    default: Date.now,
    index: { expires: '1m' }
  }
},
{
  collection: 'verify'
});

// Connect to mongodb.
mongoose.connect('mongodb://localhost/test').then(() => {
  // Create the model
  const Verify = mongoose.model('Verify', verifySchema)

  // Create a model instance.
  const v = new Verify({
    _userId: new ObjectId(),
    hash: uuid.v4()
  })

  // Save the model.
  v.save().then(() => {
    // Close the connection.
    mongoose.connection.close()
  })
})

您可以使用 MongoDB Compass 或使用 shell 检查您的索引:

> use test
> db.verify.getIndexes()

查找字段值expireAfterSeconds,它将指示为索引设置的 TTL 时间(以秒为单位)。为了更改 TTL,您需要删除 createdAt 上的索引。在 shell 中,命令将是 db.verify.dropIndex(<index_name>)db.verify.dropIndexes() 以删除集合中的所有索引。

对于更新插入文档,例如使用findOneAndUpdate,您需要将setDefaultsOnInsert: true 传递给如下选项:

// Connect to mongodb.
mongoose.connect('mongodb://localhost/test').then(() => {
  // Create the model
  const Verify = mongoose.model('Verify', verifySchema)

  const _userId = new ObjectId()
  const hash = uuid.v4()
  const options = { upsert: true, setDefaultsOnInsert: true }

  // Upsert the document.
  Verify.findOneAndUpdate( { _userId }, { hash }, options).then(() => {
    mongoose.connection.close()
  })
})

这是必需的,否则包含 TTL 索引的 createdAt 字段将不会添加到文档中。

【讨论】:

  • 当我这样做时,它不会在过期日期后自行删除。 const verify = await Verify.findOneAndUpdate( { _userId: user._id }, { hash: uuidv4() }, { upsert: true, new: true } );
  • @Steve 问题似乎是该命令默认没有设置createdAt 字段,因此 TTL 索引不在新文档上。将setDefaultsOnInsert: true 添加到选项中,它应该可以工作:mongoosejs.com/docs/api.html#model_Model.findOneAndUpdate
  • 我已更新答案以包含对 findOneAndUpdate 行为的解释。
  • 我很高兴,@Steve,很高兴我能帮上忙!
  • setDefaultsOnInsert: true 更新插入是我所缺少的,谢谢
猜你喜欢
  • 2017-01-14
  • 2019-09-23
  • 1970-01-01
  • 2020-07-05
  • 2021-05-16
  • 2018-11-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多