Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

spring-data-mongo - optional query parameters?

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

like image 677
Andrew B Avatar asked Jul 23 '12 13:07

Andrew B


People also ask

Can query params be optional?

As query parameters are not a fixed part of a path, they can be optional and can have default values.

Can I use Spring data JPA with MongoDB?

Yes, DataNucleus JPA allows it, as well as to many other databases. You make compromises by using the JPA API for other types of datastores, but it makes it easy to investigate them.

Which is better MongoTemplate or MongoRepository?

MongoTemplate is a bit more lower level where you need to write your own queries. With embedded documents and denormalization it can be easier to write complex queries with MongoTemplate. For simple things I would use MongoRepository. I've seen some examples where both are used together in a hybrid approach.

What is @document annotation in spring boot?

@Document is an annotation provided by Spring data project. It is used to identify a domain object, which is persisted to MongoDB. So you can use it to map a Java class into a collection inside MongoDB. If you don't use Spring Data, you don't need this annotation.


2 Answers

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);
like image 125
Archimedes Trajano Avatar answered Oct 17 '22 05:10

Archimedes Trajano


In addition to Archimedes's answer:
If you need the count of matched documents, replace $where with $expr.

@Query("{ $or : [ { $expr: { $eq: ['?0', 'null'] } } , { field : ?0 } ] }")
Page<Something> findAll(String query, Pageable pageable);
like image 1
Paul Lam Avatar answered Oct 17 '22 05:10

Paul Lam