You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot中如何在@Indexed注解内使用@Value配置Mongo TTL

解决MongoDB TTL索引配置不生效问题

问题根源

你遇到的核心问题是:@Indexed的expireAfter参数要求long类型的毫秒数,但你配置的10d是字符串格式,直接通过SpEL或属性绑定无法自动转换为符合要求的数值;同时Java的Duration解析需要标准ISO格式,而非自定义的10d写法。

可行解决方案

方案1:使用标准ISO Duration格式+SpEL解析

修改配置文件为Java Duration支持的ISO-8601格式:

mongo:
    data:
        expire:
            days: PT10D  # PT10D表示10天,P代表周期,T代表时间部分,D代表天

实体类中通过SpEL将Duration转换为毫秒数:

@Document(collection = "Test")
public class Test{

    @Id
    private String id;

    @Indexed(name = "expire_at", expireAfter = "#{T(java.time.Duration).parse('${mongo.data.expire.days}').toMillis()}")
    private Instant expireAt;
}

方案2:自定义配置类解析10d格式

如果你想保留10d的配置写法,创建一个配置类来解析转换:

@Component("mongoTTLConfig")
public class MongoTTLConfig {
    @Value("${mongo.data.expire.days}")
    private String expireConfig;

    public long getExpireMillis() {
        // 解析10d、3h这类简单格式,这里只处理天的情况
        long value = Long.parseLong(expireConfig.replaceAll("[^0-9]", ""));
        String unit = expireConfig.replaceAll("[0-9]", "");
        
        return switch (unit) {
            case "d" -> value * 24 * 60 * 60 * 1000;
            case "h" -> value * 60 * 60 * 1000;
            case "m" -> value * 60 * 1000;
            default -> value;
        };
    }
}

然后实体类中引用配置类的方法:

@Document(collection = "Test")
public class Test{

    @Id
    private String id;

    @Indexed(name = "expire_at", expireAfter = "#{@mongoTTLConfig.getExpireMillis()}")
    private Instant expireAt;
}

方案3:基于字段时间的TTL索引(如果你的需求是按expireAt字段值过期)

如果你的实际需求是当文档的expireAt字段时间到达后自动删除,而非创建后固定天数过期,那么只需将expireAfter设为0,然后在保存文档时给expireAt赋值:

@Document(collection = "Test")
public class Test{

    @Id
    private String id;

    @Indexed(name = "expire_at", expireAfter = 0)
    private Instant expireAt;
}

在服务层保存时注入配置并设置过期时间:

@Service
public class TestService {
    @Value("${mongo.data.expire.days}")
    private String expireDays;

    public void saveTest(Test test) {
        // 解析配置并设置expireAt为当前时间+指定天数
        long days = Long.parseLong(expireDays.replace("d", ""));
        test.setExpireAt(Instant.now().plus(Duration.ofDays(days)));
        // 执行保存操作
    }
}

验证索引是否生效

配置完成后,登录MongoDB客户端执行以下命令,检查TTL索引是否正确创建:

db.Test.getIndexes()

查看输出中是否存在expire_at索引,且expireAfterSeconds值符合预期:

  • 方案1/2中,10天对应expireAfterSeconds为864000(102460*60)
  • 方案3中,expireAfterSeconds为0

内容的提问来源于stack exchange,提问作者Susmitha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 00:37:49