Docs 菜单
Docs 主页
/
MongoDB Manual
/ / /

通过设置 TTL 使集合中的数据过期

在此页面上

  • 使 MongoDB Atlas 用户界面中的文档过期
  • 在指定的秒数后使文档过期
  • 使用筛选条件使文档过期
  • 在特定时钟时间使文档过期
  • 使用 NaN 配置的索引

本文档介绍了 MongoDB 的“生存时间”或 TTL 集合功能。TTL 集合可以将数据存储在 MongoDB 中,并让 mongod 在指定的秒数后或在特定的时钟时间自动删除数据。

您可以使托管在以下环境中的部署的数据过期:

  • MongoDB Atlas :用于在云中部署 MongoDB 的完全托管服务

数据过期对于某些类别的信息很有用,包括机器生成的事件数据、日志和仅需要保留一段有限时间的会话信息。

特殊的 TTL 索引属性支持 TTL 集合的实施。TTL 功能依赖于 mongod 中的后台线程。该线程可读取索引中的日期类型值并从集合中删除过期的文档

要创建 TTL 索引,请使用 createIndex()。指定一个日期类型或包含日期类型值的数组的索引字段。使用 expireAfterSeconds 选项指定 TTL 值(以秒为单位)。

注意

TTL 索引为单字段索引。复合索引不支持 TTL 属性。有关 TTL 索引的更多信息,请参阅 TTL 索引。

您可以使用 collMod 命令修改现有 TTL 索引的 expireAfterSeconds

如果时间序列集合包含时间戳在 1970-01-01T00:00:00.000Z 之前或 2038-01-19T03:14:07.000Z 之后为 timeField 的文档,则 TTL“生存时间”功能不会从集合中删除任何文档。

要使 Atlas 用户界面中的数据过期,请按照以下步骤操作:

1
  1. 在 MongoDB Atlas 用户界面中,单击侧边栏中的 Database

  2. 对于包含要过期的数据的数据库部署,单击 Browse Collections

  3. 在左侧导航窗格中,选择数据库。

  4. 在左侧导航窗格中,选择该集合。

2
  1. 单击 Indexes 标签页。

  2. 单击 Create Index(连接)。

3
  1. Fields 部分,输入索引键规范文档。对于此示例,请输入以下文本以对 expiresAfter 字段创建索引:

    { "expiresAfter": 1 }
  2. Options 部分,输入 expireAfterSeconds 选项。对于本示例,请输入以下文本以使数据在 expiresAfter 字段所指定值后的 1 秒过期:

    { expireAfterSeconds: 1 }
  3. 单击 Review(连接)。

  4. 单击 Confirm(连接)。

4
  1. 在左侧导航窗格中,选择包含索引的集合。

  2. 单击 Find 标签页。

  3. 单击 Insert Document(连接)。

  4. 单击 _id 字段下的文本字段,然后输入字段名称 expiresAfter

  5. 单击 expiresAfter 旁边的文本字段,输入以下值:

    2023-10-01T12:00:00.000+00:00

    该值在 2023 年 10 月 1 日 12:00 后使数据过期。

  6. 单击数据类型下拉菜单,然后将数据类型值更改为 Date

  7. 单击 Insert(连接)。

    该文档将在 expiredAfter 字段的值过后一秒钟自动过期。

    TTL 索引可能需要 1-2 秒才能使文档过期。您可能需要刷新 UI 才能看到 MongoDB Atlas 删除过期文档。

您可以在终端中设置数据过期时间为指定秒数。若要在索引字段设置数据过期时间为指定秒数后,请在保存 BSON 日期类型值的字段,或 BSON 日期类型对象数组上创建 TTL 索引,expireAfterSeconds 字段中指定一个非零的正值。当 expireAfterSeconds 字段中的秒数超过文档索引字段中指定的时间时,文档将过期失效。[1]

TTL 索引 expireAfterSeconds 值必须介于 02147483647(包含两者)之间。

例如,以下操作在 log_events 集合的 createdAt 字段上创建索引,并指定 10expireAfterSeconds 值,以将过期时间设置为 createdAt 指定的时间后十秒。

db.log_events.createIndex( { "createdAt": 1 }, { expireAfterSeconds: 10 } )

将文档添加到 log_events 集合时,将 createdAt 字段设置为当前时间:

db.log_events.insertOne( {
"createdAt": new Date(),
"logEvent": 2,
"logMessage": "Success!"
} )

当文档的 createdAt[1] 早于 expireAfterSeconds 中指定的秒数时,MongoDB 将自动从 log_events 集合中删除文档。

[1](1, 2) 如果该字段包含 BSON 日期类型对象的数组,则如果至少一个 BSON 日期类型对象早于 expireAfterSeconds 中指定的秒数,则数据将过期。

要使用特定筛选器表达式使文档过期,您可以创建一个既是部分索引又是 TTL 索引的索引。

创建部分 TTL 索引:

db.foo.createIndex(
{ F: 1 },
{
name: "Partial-TTL-Index",
partialFilterExpression: { D : 1 },
expireAfterSeconds: 10
}
)

插入两个文档,其中一个符合 partialFilterExpression 的过滤器表达式 { D : 1 }

db.foo.insertMany( [
{ "F" : ISODate("2019-03-07T20:59:18.428Z"), "D" : 3},
{ "F" : ISODate("2019-03-07T20:59:18.428Z"), "D" : 1}
] )

等待十秒钟,然后查询 foo 集合:

db.foo.find({}, {_id: 0, F: 1, D: 1})

{ D : 1 }partialFilterExpression 匹配的文档已删除(已过期)。因此, foo集合中仅保留一份文档:

{ "F" : ISODate("2019-03-07T20:59:18.428Z"), "D" : 3}

您可以在终端的指定时钟时间使数据过期。要在特定时钟时间使文档过期,请首先在保存 BSON 日期类型值或 BSON 日期类型对象数组的字段上创建 TTL 索引,并指定expireAfterSeconds0 。 对于集合中的每个文档,将索引日期字段设置为与文档到期时间相对应的值。 如果索引日期字段包含过去的日期,MongoDB 会认为该文档已过期。

例如,以下操作在 log_events 集合的 expireAt 字段上创建索引并指定 0expireAfterSeconds 值:

db.log_events.createIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } )

对于每个文档,将 expireAt 的值设置为与文档应过期的时间相对应。例如,下面的insertOne()操作添加了一个在July 22, 2013 14:00:00过期的文档。

db.log_events.insertOne( {
"expireAt": new Date('July 22, 2013 14:00:00'),
"logEvent": 2,
"logMessage": "Success!"
} )

当文档的 expireAt 值早于 expireAfterSeconds 中指定的秒数(在本例中为早于 0 秒)时,MongoDB 将自动从 log_events 集合中删除文档。 因此,数据在指定的expireAt值处过期。

警告

可能的数据丢失

当 TTL 索引将 expireAfterSeconds 设置为 NaN 时,升级、降级和某些同步操作可能会导致意外行为并可能导致数据丢失。

请勿在 TTL 索引配置中将 expireAfterSeconds 设置为 NaN

在 MongoDB 5.0 之前,当 TTL 索引将 expireAfterSeconds 设置为 NaN 时,MongoDB 会记录错误并且不会删除任何记录。

从 MongoDB 5.0.0 - 5.0.13(和 6.0.0 - 6.0.1),NaN 被视为 0。如果通过将 expireAfterSeconds 设为 NaN 来配置某一 TTL 索引,则使用 TTL 进行索引的所有文档均会立即过期。

从 MongoDB 5.0.14(和 6.0.2)开始,服务器将不再使用将 expireAfterSeconds 设置为 NaN 的 TTL 索引。

不过,在某些情况下仍可能出现意外行为。文件可能过期:

  • 在从 MongoDB 5.0.0 - 5.0.13(或 6.0.0 - 6.0.1)初始同步到早期版本期间。

  • 当从早期版本升级到 MongoDB 5.0.0 - 5.0.13 时。

  • 从5之前的集合中恢复集合时。将0 mongodump导入到 MongoDB 5中。 0 。 0 - 5 。 0 。 13 (或6 . 0 . 0 - 6 . 0 . 1 )实例。

为了避免出现问题,请删除或更正任何配置错误的 TTL 索引。

1

mongosh Shell 中运行以下脚本。该脚本在旧版mongo Shell 中不起作用。

function getNaNIndexes() {
const nan_index = [];
const dbs = db.adminCommand({ listDatabases: 1 }).databases;
dbs.forEach((d) => {
if (d.name != 'local') {
const listCollCursor = db
.getSiblingDB(d.name)
.runCommand({ listCollections: 1 }).cursor;
const collDetails = {
db: listCollCursor.ns.split(".$cmd")[0],
colls: listCollCursor.firstBatch.map((c) => c.name),
};
collDetails.colls.forEach((c) =>
db
.getSiblingDB(collDetails.db)
.getCollection(c)
.getIndexes()
.forEach((entry) => {
if (Object.is(entry.expireAfterSeconds, NaN)) {
nan_index.push({ ns: `${collDetails.db}.${c}`, index: entry });
}
})
);
}
});
return nan_index;
};
getNaNIndexes();
2

使用 collMod 命令更新脚本发现的任何错误配置的 expireAfterSeconds 值。

作为替代方案,您可以 drop 任何配置错误的 TTL 索引,并稍后使用 createIndexes 命令重新创建这些索引。

← TTL 索引