mongodb 使用TTL索引时,如何正确地将文档标记为“永不过期”

euoag5mw  于 2022-12-03  发布在  Go
关注(0)|答案(1)|浏览(188)

我在用户创建的帖子上使用Mongo的TTL索引。每个帖子都有expiresAt字段,这是TTL索引使用的日期。
管理员可以“突出显示”帖子,从而使它永远不会过期。
我不确定如何正确执行此操作,正在考虑以下两种方法
1.将expiresAt设置为未来的某个大数字,即9999年
1.删除或设置expiresAt字段为“未定义”
最好的方法是什么?理想情况下,同时删除文档上的索引,以便不必要地存储文档?

yqhsw0fo

yqhsw0fo1#

正如您所建议的,有多种方法可以实现这一点。一般而言,TTL索引具有以下行为:
如果文档中的索引字段不是日期或包含一个或多个日期值的数组,则文档不会过期。
如果文档不包含索引字段,则文档不会过期。
这个行为证实了您的第二个想法(取消设置expiresAt)是可行的。您还提到解决方案应该“* 理想情况下也删除文档上的索引,这样就不会不必要地存储它?*”基于此,我将通过使用TTL和Partial索引来实现此目的。例如:

db.foo.createIndex(
  { expiresAt: 1 },
  { expireAfterSeconds: 3600, partialFilterExpression: { expiresAt: {$exists:true} } 
})

如果我们有以下三个文件:

test> db.foo.find()
[
  { _id: 1, expiresAt: ISODate("2022-11-27T17:09:23.394Z") },
  { _id: 2, expiresAt: ISODate("2022-11-27T17:09:26.718Z") },
  { _id: 3 }
]

我们可以看到,在我们的索引中只捕获了前两个文档,这意味着第三个文档不占用空间,也不会过期;

test> db.foo.find().hint({expiresAt:1}).explain("executionStats").executionStats.totalKeysExamined
2

如果文档默认将某个highlighted字段设置为false,则另一种方法可能是:

db.foo.createIndex(
  { expiresAt: 1 },
  { expireAfterSeconds: 3600, partialFilterExpression: { highlighted: false } 
})

这种方法的有趣之处在于,它允许您保留原始过期值(在原始字段中),以备以后出于某种原因需要引用:

test> db.foo.find()
[
  {
    _id: 1,
    expiresAt: ISODate("2022-11-27T17:09:23.394Z"),
    highlighted: false
  },
  {
    _id: 2,
    expiresAt: ISODate("2022-11-27T17:09:26.718Z"),
    highlighted: false
  },
  {
    _id: 3,
    expiresAt: ISODate("2022-11-27T17:13:25.929Z"),
    highlighted: true
  }
]
test> db.foo.find().hint({expiresAt:1}).explain("executionStats").executionStats.totalKeysExamined
2

相关问题