使用Morphia 1.3.2聚合MongoDB 3.6遇到的游标选项问题
解决Morphia 1.3.2 + MongoDB 3.6聚合操作的cursor选项问题
我之前也踩过这个坑,MongoDB 3.6的这个变更确实给用老版本Morphia的开发者带来了不少困扰,下面给你具体的解决思路和代码示例:
问题根源
MongoDB官方文档明确:3.6版本移除了不带
cursor选项的aggregate命令使用(除非命令包含explain选项),也就是说所有正常的聚合请求必须显式指定cursor参数,哪怕只是空的配置。而Morphia 1.3.2默认不会自动添加这个选项,导致请求被MongoDB拒绝。
解决方案:显式指定cursor选项
你可以通过两种方式在Morphia的聚合管道中添加cursor配置:
方式1:直接在Pipeline链中调用cursor()
这是最简洁的方式,直接在聚合管道的末尾添加cursor配置,传入空的Document即可(MongoDB会使用默认的cursor参数):
// 假设你的实体类是YourEntity,结果映射类是ResultType AggregationPipeline pipeline = datastore.createAggregation(YourEntity.class) .match(QueryBuilder.start("field").equal("value").get()) // 你的match条件 .unwind("arrayField") // 你的unwind字段 .cursor(new Document()); // 关键:添加cursor选项 // 执行聚合并获取结果 List<ResultType> results = pipeline.asList(ResultType.class);
如果需要自定义cursor的batchSize等参数,也可以在Document里指定:
.cursor(new Document("batchSize", 200))
方式2:通过AggregationOptions配置
如果需要统一配置聚合的其他选项(比如allowDiskUse),可以用AggregationOptions来封装cursor:
// 构建聚合选项,包含cursor配置 AggregationOptions options = AggregationOptions.builder() .cursor(new Document()) // 必须添加cursor .allowDiskUse(true) // 可选:如果聚合数据量大,开启磁盘使用 .build(); // 创建带选项的聚合管道 AggregationPipeline pipeline = datastore.createAggregation(YourEntity.class, options) .match(...) .unwind(...); List<ResultType> results = pipeline.asList(ResultType.class);
特殊情况:直接发送aggregate命令
如果你是直接通过MongoDB的命令方式执行聚合(而非Morphia的Pipeline API),也要确保命令中包含cursor字段:
Document aggregateCommand = new Document("aggregate", "your_collection_name") .append("pipeline", Arrays.asList( new Document("$match", new Document("field", "value")), new Document("$unwind", "$arrayField") )) .append("cursor", new Document()); // 必须添加这个字段 // 执行命令 Document result = datastore.getDB().command(aggregateCommand);
这样调整之后,你的聚合请求就符合MongoDB 3.6的要求了,应该就能正常执行了。
内容的提问来源于stack exchange,提问作者Kevin Van Den Broek
相关产品推荐
相关产品推荐

