Description
Hi. When you create an aggregation pipeline and use a sort operation with Sort.unsorted()
an exception is thrown (UncategorizedMongoDbException
). The reason for the exception is, that the sort stage is created but it is simply an empty object. You can reproduce the behavior with the following example:
import org.bson.Document;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Query;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.newAggregation;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.sort;
/* Example documents in database "test", collection "test" (not strictly required to reproduce the exception):
{
"_id" : ObjectId("51a4da9b292904caffcff6eb"),
"x" : 0
}
{
"_id" : ObjectId("51a4da9b292904caffcff6ec"),
"x" : 1
}
{
"_id" : ObjectId("51a4da9b292904caffcff6ed"),
"x" : 2
}
*/
@SpringBootApplication
public class MongodbSortSscce implements CommandLineRunner {
private final MongoTemplate mongoTemplate;
public MongodbSortSscce(MongoTemplate mongoTemplate) {
this.mongoTemplate = mongoTemplate;
}
public static void main(String[] args) {
SpringApplication.run(MongodbSortSscce.class, args);
}
@Override
public void run(String... args) {
//results in: {"find": "test", "filter": {}}
mongoTemplate.find(new Query().with(Sort.unsorted()), Document.class, "test"); //works
//results in: {"aggregate": "test", "pipeline": [{"$sort": {"x": 1}}]}
mongoTemplate.aggregate(newAggregation(sort(Sort.by("x"))), "test", Document.class); //works
//results in: {"aggregate": "test", "pipeline": [{"$sort": {}}]}
mongoTemplate.aggregate(newAggregation(sort(Sort.unsorted())), "test", Document.class); //fails with "$sort stage must have at least one sort key"
}
}
You can see that it works when you sort by an arbitrary field (x
in the example above). It also works when using find
instead of aggregate
. In this case the sort
operation never reaches the MongoDB(-driver) but is removed somewhere in between. This should also happen for an aggregation in my opinion.
Of course a developer can make sure that an unsorted
sort operation is never added to the pipeline (in a real world scenario the sort field will probably come from a URL parameter or something like that - so it's not as obvious as in the example) but that implies that the developer is aware that an exception will be thrown otherwise.