Spring Data MongoDB如何基于MongoDB服务端时间实现插入日期加指定天数
Spring Data MongoDB服务端日期增量更新实现方案
Update.currentDate()对应的MongoDB $currentDate修饰符仅支持直接将字段赋值为MongoDB服务端当前时间,不支持直接在赋值的同时做算术运算。要实现不依赖应用服务器时间的日期加X天需求,可以用以下方案:
推荐方案:使用聚合更新管道(MongoDB 4.2+ + Spring Data MongoDB 2.2+)
该方案所有逻辑都在MongoDB服务端执行,时间源和$currentDate完全一致,全程不依赖应用服务器的时间配置:
- 用MongoDB系统变量
$$NOW获取服务端当前时间(和$currentDate时间源完全相同) - 用
$add运算符给时间加上X天对应的毫秒数(1天=86400000毫秒) - 直接赋值给目标日期字段
代码示例:
// 要增加的天数 int addDays = 7; long timeToAdd = (long) addDays * 24 * 60 * 60 * 1000; // 构造更新规则 Update update = Update.update( "yourDateField", AggregationExpression.from("{ $add: [\"$$NOW\", " + timeToAdd + "] }") ); // 执行更新,示例为匹配_id为指定值的文档 mongoTemplate.updateFirst( Query.query(Criteria.where("_id").is("yourDocumentId")), update, YourEntityClass.class );
Spring Data 3.x版本可以使用更类型安全的写法:
Update update = Update.update( "yourDateField", ArithmeticOperators.Add.valueOf("$$NOW").add((long) addDays * 86400000) );
备选方案:分两次更新(兼容低版本MongoDB)
如果使用的MongoDB版本低于4.2,不支持聚合更新管道,可以分两步实现,缺点是会产生两次数据库交互:
Query query = Query.query(Criteria.where("_id").is("yourDocumentId")); long timeToAdd = (long) addDays * 86400000; // 第一步:用$currentDate将字段设置为服务端当前时间 Update setCurrentTimeUpdate = Update.currentDate("yourDateField"); mongoTemplate.updateFirst(query, setCurrentTimeUpdate, YourEntityClass.class); // 第二步:给日期字段累加对应毫秒数(MongoDB支持对Date类型执行inc操作,增量单位为毫秒) Update addDaysUpdate = new Update().inc("yourDateField", timeToAdd); mongoTemplate.updateFirst(query, addDaysUpdate, YourEntityClass.class);
注意事项
- 两种方案的时间都来自MongoDB服务端,不会受应用服务器时区、时间偏差的影响,和Oracle中用sysdate做算术运算的效果一致。
- 日期运算的单位是毫秒,需要注意整数溢出问题,转成long类型计算避免溢出。
内容的提问来源于stack exchange,提问作者Khanna111
相关产品推荐
相关产品推荐

