MongoDB Java驱动中如何使用dateAdd批量更新多条记录
问题场景
现有MongoDB集合内的文档结构如下:
[ { "user": "abc", "seconds": 1111, "time": ISODate("2020-05-05T00:00:00Z") }, { "user": "abc", "seconds": 2222, "time": ISODate("2020-05-05T00:00:00Z") } ]
需求是为每条匹配记录新增time2字段,取值为当前文档自身time字段值加上seconds字段对应秒数的计算结果。
当前使用的数据库版本为MongoDB 5.0,原生支持$dateAdd聚合运算符,搭配4.6.0版本MongoDB Java驱动编写的如下更新代码,执行后未得到预期结果:
var alerts = db.getCollection("alerts"); alerts.updateMany(eq("user", user), set(new Field<>("time2", new Document("$dateAdd", new Document("startDate", "$time") .append("unit", "second") .append("amount", "$seconds")) )));
问题原因
- 直接在
Updates.set中传入构造的$dateAddDocument时,Java驱动会将该对象识别为普通字面量值,不会解析为聚合表达式,最终写入的time2字段会是整个$dateAdd结构的文档,而非计算后的日期结果。 - 普通更新语法不支持引用文档自身字段做动态计算,所有涉及字段引用、聚合运算符的更新操作,必须使用聚合管道更新语法执行。
解决方案
将更新逻辑包裹为聚合管道格式传入updateMany,驱动就会将后续内容识别为聚合表达式执行动态计算,修正后的代码如下:
import java.util.List; import com.mongodb.client.model.Updates; import org.bson.Document; // 省略集合初始化逻辑 alerts.updateMany( eq("user", user), List.of( Updates.set("time2", new Document("$dateAdd", new Document("startDate", "$time") .append("unit", "second") .append("amount", "$seconds") ) ) ) );
也可以直接用Document构造聚合更新阶段,执行效果完全一致:
alerts.updateMany( eq("user", user), List.of( new Document("$set", new Document("time2", new Document("$dateAdd", new Document("startDate", "$time") .append("unit", "second") .append("amount", "$seconds") ) ) ) ) );
代码执行后time2字段会正确生成计算结果:第一条记录的time2为2020-05-05T00:18:31Z(1111秒折合18分31秒),第二条为2020-05-05T00:37:02Z。
聚合管道更新语法从MongoDB 4.2版本开始支持,当前使用的5.0版本和4.6.0版本Java驱动完全兼容该写法。
内容的提问来源于stack exchange,提问作者Ahmed Ashour
相关产品推荐
相关产品推荐

