24

I am trying to execute an aggregate operation using Spring Data MongoDB 3.6-rc4.

Aggregation agg = newAggregation(
    lookup("orders", "orderId", "_id", "order") 
);
List<BasicDBObject> results = mongoOperations.aggregate(agg, "transactions", BasicDBObject.class).getMappedResults();

But get the following error on running the query

2017-11-24 17:03:41,539 WARN  org.springframework.data.mongodb.core.MongoTemplate : Command execution of { "aggregate" : "transactions" , "pipeline" : [ { "$lookup" : { "from" : "orders" , "localField" : "orderId" , "foreignField" : "_id" , "as" : "order"}}]} failed: The 'cursor' option is required, except for aggregate with the explain argument
2017-11-24 17:03:41,574 ERROR org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: Command execution failed:  Error [The 'cursor' option is required, except for aggregate with the explain argument], Command = { "aggregate" : "transactions" , "pipeline" : [ { "$lookup" : { "from" : "orders" , "localField" : "orderId" , "foreignField" : "_id" , "as" : "order"}}]}; nested exception is 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" }] with root cause
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" }
    at com.mongodb.CommandResult.getException(CommandResult.java:80) ~[mongo-java-driver-3.5.0.jar:na]
    at com.mongodb.CommandResult.throwOnError(CommandResult.java:94) ~[mongo-java-driver-3.5.0.jar:na]
    at org.springframework.data.mongodb.core.MongoTemplate.handleCommandError(MongoTemplate.java:2100) ~[spring-data-mongodb-1.10.8.RELEASE.jar:na]
    at org.springframework.data.mongodb.core.MongoTemplate.aggregate(MongoTemplate.java:1577) ~[spring-data-mongodb-1.10.8.RELEASE.jar:na]
    at org.springframework.data.mongodb.core.MongoTemplate.aggregate(MongoTemplate.java:1505) ~[spring-data-mongodb-1.10.8.RELEASE.jar:na]

Thanks in advance!!

mp911de
  • 17,546
  • 2
  • 55
  • 95
rohit
  • 953
  • 5
  • 15
  • 31

13 Answers13

25

MongoDB changed in 3.6 how the aggregation command works. Aggregations require now a cursor. We adapted Spring Data MongoDB 2.1 but not previous versions.

Aggregations must be invoked through the collection's aggregate(…) method instead of calling the command directly. This is also the reason why we didn't backport the change. executeCommand(…) is no longer called and we don't want to break compatibility in a bugfix release.

The easiest approach for you can be to override the aggregate(…) method and call the appropriate method, DBCollection.aggregate(…) with the mapped aggregation pipeline.

mp911de
  • 17,546
  • 2
  • 55
  • 95
  • Is MongoDB 3.4 compatible with current version of spring data, and supports aggregates ? – rohit Nov 29 '17 at 05:31
  • Yes, it is fully supported. – mp911de Nov 29 '17 at 05:31
  • 1
    Hi, guys. Recently faced with the same problem. As far I understand I should do one of the following: a) waiting for release of Spring Data MongoDB 2.1, b) create my own class inherited from MongoTemplate, and override aggregate() method by introducing all changes contained in PR https://github.com/spring-projects/spring-data-mongodb/pull/515. Am I right? – Lesha Pipiev Jan 24 '18 at 18:23
  • A fixed Spring Data release is available as of today. – mp911de Jan 24 '18 at 18:30
  • @mp911de, thank you for the fast reply. But there is another one problem :) I'm using spring-data-mongodb through spring-boot-starter-data-mongodb which is currently coupled with spring-data-mongodb v1.10.9. BTW, I don't see v2.1.0 in https://mvnrepository.com/artifact/org.springframework.data/spring-data-mongodb-parent. Thank you again. – Lesha Pipiev Jan 24 '18 at 19:19
  • hello @mp911de could you show an example using dbcollection .aggregate? I tried to updated spring-data, but doesn't up the application, we need update spring-boot-2 and I have other libs which are not yet supported (apache-camel) – Renato Garcia Mar 06 '18 at 14:00
11

I was using:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.8.RELEASE</version>
    <relativePath></relativePath>
</parent>

Then after upgraded my dependency to a higher version, the issue was resolved:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.10.RELEASE</version>
    <relativePath></relativePath>
</parent>
Pang
  • 9,564
  • 146
  • 81
  • 122
Andrei Maimas
  • 695
  • 1
  • 9
  • 9
4

Upgrading the spring boot version didn't work for me. Changing outputmode as cursor as providing a cursor is mandatory, worked. Verified in mongo 3.6

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()));
}
Pratik Saxena
  • 191
  • 2
  • 10
3

It seems Pull Request mentionned by @mp911de has been release in version 1.10.10 of Spring Data MongoDB. So you can either

  • upgrade your Spring Data MongoDB dependency to 1.10.10.RELEASE
  • upgrade your spring-boot-starter-data-mongodb dependency to 1.5.10.RELEASE
Atari
  • 31
  • 2
1

I have also faced this type of error when using Mongodb version 3.6.2.

Check your version of org.springframework.data in pom.xml

For me, i have changed org.springframework.data version to 2.0.3.RELEASE and my problem was solved.

Adarsh Patel
  • 103
  • 1
  • 6
1
Just updating the spring boot version works for me.
This is the version that I have used and worked....
<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.10.RELEASE</version>
    </parent>
amit kumar
  • 59
  • 1
  • 1
  • 11
  • We have upgraded MongoDB from 3.4 to 5.0, Faced the same issue. But this verison change solved the issue. Thanks a lot for the solution you saved my day with lots of code changes. – Sumit Sharma Sep 23 '21 at 23:28
1

You can use cursor option available with aggregate query pipeline.

{cursor: { batchSize: batch_size }}

https://docs.mongodb.com/manual/reference/method/db.collection.aggregate/

Aggregation.newAggregation(AggregationOperation... operations).withOptions(new AggregationOptions(false,false,new Document().append("batchSize" , batch_size))) may help in this case

mhvr
  • 11
  • 2
0

I have also faced this type of error when using org.springframework.data version 1.10.3.RELEASE. And then i have changed version to 2.0.5.RELEASE and my problem was solved.

Giahu
  • 1
0

Solved the issue by upgrading spring boot to the '2.1.3.RELEASE' version.

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <!--<version>1.5.10.RELEASE</version>-->
        <relativePath></relativePath>
    </parent>
Andrei Maimas
  • 695
  • 1
  • 9
  • 9
0

If you are having this issue and you are using Studio 3T, there is an option in the Options tab, just check it:

enter image description here

Lucas Vall
  • 49
  • 3
0

Your command no longer works due to a change in mongodb driver change in version 3.6. You need to invoke it from dbCollection.aggregate(...) method instead.

whoami - fakeFaceTrueSoul
  • 17,086
  • 6
  • 32
  • 46
krishan
  • 49
  • 3
0

I've tried all above (short of changing the code to using a cursor) to no avail.

In the end, I had to upgrage

'mongo-java-driver'       : '3.6.2'

Then it worked.

Nestor Milyaev
  • 5,845
  • 2
  • 35
  • 51
0
  1. Use Spring Boot 2.0.0 or later.
  2. Add AggregationOptions with cursor to your Aggregation:
AggregationOptions aggregationOptions = AggregationOptions.builder()
    .allowDiskUse(true)
    .cursor(new Document())
    .build();
Aggregation aggregation = Aggregation.newAggregation(aggregationOperations)
    .withOptions(aggregationOptions);
  1. Call aggregateStream() (not aggregate()) method of MongoOperations. This method utilizes the cursor responded by MongoDB:
mongoOps.aggregateStream(aggregation, "collection", MyEntity.class)
gelin
  • 111
  • 1
  • 4