Mongo4.4.0下Reactive MongoTemplate聚合提示cursor选项必填错误如何解决?
问题原因
Spring Data MongoDB 3.2.x版本的ReactiveMongoTemplate会默认给所有响应式聚合请求自动添加cursor参数,但MongoDB 4.2+明确规定:如果聚合的最后一个阶段是$merge/$out这类写操作阶段,聚合请求不能携带cursor参数,二者冲突就触发了本次报错。你之前主动添加cursorBatchSize/cursor参数的操作反而会加重冲突。
解决方案
第一步:调整聚合选项配置,禁用自动添加游标,同时标记聚合不需要返回输出
核心配置是添加skipOutput(true),标记当前聚合为写操作、不需要返回结果集,框架会自动禁用cursor参数:AggregationOptions options = AggregationOptions.builder() .allowDiskUse(true) .skipOutput(true) .build();第二步:调整方法返回值与调用逻辑
$merge是写操作,执行完成后默认不会返回业务实体,如果你不需要获取写入后的文档,直接返回操作完成的信号即可;如果确实需要返回写入后的结果,需要在merge配置中添加returnNewDocuments(true),同时去掉skipOutput配置。
无返回值的完整代码示例:public Mono<Void> someMethod(String param) { return reactiveMongoTemplate.aggregate(Aggregation.newAggregation(X.class, Aggregation.match(Criteria.where("test").is(param)), Aggregation.group("field") .first("value").as("value") .first("test").as("test"), Aggregation.group() .first("test").as("test") .push(new BasicDBObject() .append("k", "$_id") .append("v", "$value") ) .as("array"), Aggregation.replaceRoot( MergeObjects.merge( new BasicDBObject().append("_id", "$test"), ArrayToObject.arrayValueOfToObject("array") ) ), Aggregation.project(getFields()), Aggregation.merge() .into(MergeOperationTarget.collection("test")) .on("id") // 若需要返回写入后的新文档,加上下面这行,同时删除skipOutput配置 // .returnNewDocuments(true) .build() ).withOptions(AggregationOptions.builder() .allowDiskUse(true) // 不需要返回结果就保留该配置,需要返回则删除 .skipOutput(true) .build()), Test.class) // 不需要返回结果用then(),需要返回结果则保留single() .then(); }第三步:检查嵌入式Mongo兼容版本
你当前使用的flapdoodle嵌入式Mongo需要匹配4.4版本的协议,建议升级到de.flapdoodle.embed:de.flapdoodle.embed.mongo:4.12.0及以上版本,避免模拟实例本身的兼容bug导致问题复现。
内容的提问来源于stack exchange,提问作者BrianM
相关产品推荐
相关产品推荐

