spring-projects / spring-data-mongodb

Provides support to increase developer productivity in Java when using MongoDB. Uses familiar Spring concepts such as a template classes for core API usage and lightweight repository style data access.
https://spring.io/projects/spring-data-mongodb/
Apache License 2.0
1.62k stars 1.09k forks source link

ReactiveStringBasedAggregation computes pipeline stages with domainClass instead of return type #3532

Open dnijssen opened 3 years ago

dnijssen commented 3 years ago

Currently the #computePipelineStage(String, ConvertingParameterAccessor, ParameterBindingDocumentCodec) method in the ReactiveStringBasedAggregation class maps the pipeline operation sources to the domain class, resulting in fields in a $project stage being incorrectly being resolved as _id as its name in the expected return type (Bar) -> namely identifier

Consider the following repository with an aggretion query, and 2 data models;

@Repository
interface FooRepository extends ReactiveMongoRepository<Foo, String> {

    @Aggregation(pipeline = {
            "{ $match : { _id : '?0' } }",
            "{ $replaceRoot : { newRoot : '$bar' } }",
            "{ $project : { identifier : 1 } }"
    })
    Mono<Bar> findBarBy(String identifier);
}

@Getter
@Setter
@Document
class Foo {

    @Id private String identifier;
    private Bar bar;
}

@Getter
@Setter
@Document
class Bar {

    private String identifier;
}

Executing the aggregation results in an instance of Bar , however the identifier is null , due the fact that the ReactiveStringBasedAggregation maps the pipeline stages to the domain class and identifier is being transformed to _id

Added a sample project -> https://github.com/dnijssen/mongodb-aggregation

christophstrobl commented 3 years ago

Thanks for bringing this up! The methods return type is used for mapping the result documents while the pipeline is mapped against the repository domain type and does not support switching that one via $replaceRoot. However, switching the mapping target type based on a domain types property, sounds like an interesting improvement. If you got further suggestions in this direction or even have time for a PR (which would speed up the process) we'd be more than happy to continue the discussion.