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

Repository query keyword IS_EMPTY not supported #4606

Open ssppooff opened 10 months ago

ssppooff commented 10 months ago

The documentation for repository query keywords (link) mentions support for the IsEmpty keyword, however, it fails with "Unsupported keyword" when used.

Steps to reproduce 0) spring initializr:

1) Inside file with @SpringBootApplication, add the code below 2) Start the app (no need for a running Mongo instance to get the exception)

interface CustomRepository : ReactiveMongoRepository<CustomData, String> {
    fun findByIdIsEmpty(id: String): Mono<Boolean>
}

data class CustomData(val id: String)

@Component
class Demo(val customRepository: CustomRepository) {
    @Bean
    fun accessRepo() {
        customRepository.findByIdIsEmpty("non-existent").block()
    }
}

Result Error creating bean 'accessRepo', caused by org.springframework.beans.BeanInstantiationException: Failed to instantiate [void]: Factory method 'accessRepo' threw exception with message: Unsupported keyword

The exception is thrown inside org.springframework.data.mongodb.repository.query.from (line number 254), because the switch-statement above (line 168) has no case for IS_EMPTY, even though the keyword is defined in org.springframework.data.repository.query.parser.Type.

christophstrobl commented 10 months ago

True, the documentation is misleading as the repository sections lists the generic overview from data-commons which holds the entire list of supported keywords.

Supporting IS_EMPTY would be an enhancement and we'd have to define it's behaviour given the various scenarios the MongoDB data model allows.

I could imagine using an $eq comparision to build the support. Like { field : { $eq : "" } } would be sufficient for simple String. Collections could be checked with { field: { $size: 0 } } and objects with { field : { $eq : {} } }. Numeric values, should error, though one might argue a stored null may be considered empty, but what about primitive types then. Generic types in the java domain model may also be tricky and we'd need to consider @Field(targetType=...) to pick the right format.