【问题标题】:Spring - mongodb - aggregation - The 'cursor' option is requiredSpring - mongodb - 聚合 - 'cursor' 选项是必需的
【发布时间】:2018-07-07 12:09:06
【问题描述】:

执行以下聚合管道:

public void getMostLikedItems () {
        UnwindOperation unwind = Aggregation.unwind("favoriteItems");
        GroupOperation group = Aggregation.group("favoriteItems").count().as("likes");
        SortOperation sort = Aggregation.sort(Sort.Direction.DESC, "likes");

        Aggregation aggregation = newAggregation(unwind, group, sort);
        DBObject result = mongoTemplate.aggregate(aggregation, "users", LikedItem.class).getRawResults();
}

抛出以下异常:

com.mongodb.MongoCommandException: Command failed with error 9: 'The 'cursor' option is required, except for aggregate with the explain argument' on server localhost:27017. The full response is { "ok" : 0.0, "errmsg" : "The 'cursor' option is required, except for aggregate with the explain argument", "code" : 9, "codeName" : "FailedToParse" }

我不明白这里的光标选项是什么意思。应该在哪里配置这个选项?

编辑这是一个示例用户文档

{
  "_id": "5a6df13552f42a34dcca9aa6",
  "username": "user1",
  "password": "$2a$10$p0OXq5PPa41j1e4iPcGZHuWjoKJ983sieS/ovFI.cVX5Whwj21WYi",
  "favoriteItems": [
    {
      "_id": "5a0c6b2dfd3eb67969316d6d",
      "name": "item1",
      "city": "Rabat"
    },
    {
      "_id": "5a0c680afd3eb67969316d0b",
      "name": "item2",
      "city": "Rabat"
    }
  ]
}

【问题讨论】:

  • 你的 spring mongo jar 版本是什么?看看这个helps
  • @Veeram 我的版本是 3.4.3。我之前找到了该帖子,但我并没有完全得到解决方案。您能否通过基本示例或示例链接帮助我理解它?
  • 我的意思是你的 spring mongo db jar 版本
  • 我有 v1.5.9。对不起,我的坏事

标签: java spring mongodb spring-boot aggregation-framework


【解决方案1】:

来自文档。

MongoDB 3.4 不赞成使用不带游标的聚合命令 选项,除非管道包含解释选项。什么时候 使用聚合命令内联返回聚合结果, 使用默认批量大小光标指定光标选项:{} 或 在游标选项 cursor: { batchSize: }。

您可以在 Spring Mongo 2.x 版本中将 batchSizeAggregationOptions 一起传递

Aggregation aggregation = newAggregation(unwind, group).withOptions(newAggregationOptions().cursorBatchSize(100).build());

使用默认批量大小

Aggregation aggregation = newAggregation(unwind, group).withOptions(newAggregationOptions().cursor(new Document()).build());

【讨论】:

  • 我的spring boot父项目是1.5.9版本。我可以将 spring data mongodb 升级到版本 2 吗?抱歉,如果这超出了问题的范围
  • Np。你看到AggregationOptions 类了吗?您可以在您的 Pom 依赖项中 <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb</artifactId> <version>2.0.2.RELEASE</version> </dependency> 下载 2.0 版本。顺便说一句,我会检查 spring boot 1.5.9 提供了什么版本的 spring mongo。
  • 1.5.9 引导引用了具有 AggregationOptions 类的 1.10.9 spring mongo 版本。所以你可以试试Aggregation aggregation = newAggregation(unwind, group).withOptions(newAggregationOptions().cursor(new BasicDBObject());
  • 不是真的,在我将 spring mongo jar 升级到 2.0.3 后,我的应用程序抛出了其他我目前无法处理的异常,所以我回滚到默认的 spring-boot-starter-data-mongodb。我尝试的是newAggregationOptions().cursor(new BasicDBObject("batchSize", 100)).build(),但仍然没有结果。
  • 在 boot 1.5 / data-mongo 1.10 中,mongoTemplate.aggregate(...).getRawResults() 返回一个映射此结构的DBObject{ "cursor" : { "firstBatch" : [ {"_id" : ObjectId("...")}, {"_id" : ObjectId("...")}, ], "id" : NumberLong(0), "ns" : "..." }, "ok" : 1.0, "operationTime" : ... }。您必须使用 DBObject.get(...) 遍历 cursor.firstBatch 才能获得实际的查询结果,Spring 无法从光标映射结果。 (这很难读,抱歉)
【解决方案2】:
'The 'cursor' option is required, except for aggregate with the explain argument'

当您使用不兼容的 MongoDB 和 Spring-data-mongo 版本时,Spring Data 中会出现此类错误。

虽然您可以通过解释、游标参数获得 rawResults。

Aggregation aggregation = Aggregation.newAggregation(group).withOptions( new AggregationOptions(allowDiskUse, explain, cursor));

//try with .withOptions( new AggregationOptions(true,false,new Document()));

通过注释参数传递,您将在 rawResult 中得到结果,但它不会映射到给定的 outType.class。

要获得映射结果,您必须根据您的 MongoDb 版本下载 spring-data 版本的正确依赖项。

编辑

我使用过 Spring 5.0.3 版Spring-data-mongoDB 2.0.3 版 它工作正常。

【讨论】:

    【解决方案3】:

    您可以将输出模式作为光标提供,因为必须提供光标

    List<DBObject> list = new ArrayList<DBObject>();
    list.add(unwind.toDBObject(Aggregation.DEFAULT_CONTEXT));
    list.add(group.toDBObject(Aggregation.DEFAULT_CONTEXT));
    list.add(sort.toDBObject(Aggregation.DEFAULT_CONTEXT));
    
    DBCollection col = mongoTemplate.getCollection("users");
    
    Cursor cursor = col.aggregate(list, AggregationOptions.builder().allowDiskUse(true).outputMode(OutputMode.CURSOR).build());
    
    List<AggregationResultVO> result = new ArrayList<AggregationResultVO>();
    
    while(cursor.hasNext()) {
         DBObject object = cursor.next();
         result.add(new AggregationResultVO(object.get("aggregationResultId").toString()));
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-29
      • 2017-10-12
      • 2018-10-10
      • 1970-01-01
      • 1970-01-01
      • 2019-05-09
      • 2022-01-09
      • 1970-01-01
      相关资源
      最近更新 更多