I am using spring-data mongo with the JSON based query methods, and am unsure how to allow optional parameters in a search query.
For instance – say I had the following function
@Query("{ 'name' : {$regex : ?0, $options : 'i'}, 'createdDate' : {$gte : ?1, $lt : ?2 }} }") List<MyItem> getItemsLikeNameByDateRange(String name, Date startDateRange, Date endDateRange);
-but I didnt want to apply the name regex match, or not apply a date range restriction if NULL values were passed to the method.
At the moment it looks like I might have to build the query using the mongoTemplate.
Are there any alternatives – or is using mongoTemplate the best option?
Thanks
Advertisement
Answer
To implement this in Boolean logic I do the following and the conversion to operations that are available in programming languages
:query != null -> field == :query !(:query != null) || (field == :query) (:query == null) || (field == :query)
In plain SQL, this is done as
where (null = :query) or (field = :query)
In MongoDB this is done through the $where
{ $where: '?0 == null || this.field == ?0' }
We can speed this up a little by using Mongo Operations rather than building everything to the function at the expense of some readability. does not work unfortunately.
{ $or : [ { $where: '?0 == null' } , { field : ?0 } ] }
So what you have is
@Query("{ $or : [ { $where: '?0 == null' } , { field : ?0 } ] }") List<Something> findAll(String query, Pageable pageable);
This can be further expanded to handle arrays for in/all clauses
@Query("{ $or : [ { $where: '?0.length == 0' } , { field : { $in : ?0 } } ] }") List<Something> findAll(String query, Pageable pageable);