I have the following problem. Lets say I have the following model object:
class Person {
String id;
String firstName;
String lastName;
Map<String, String> properties;
}
In the properties map, you can insert any kind of property, there are no constrains.
The above object is saved in a MongoDB which looks like this:
public interface PersonRepo extends MongoRepository<Person, String> {
}
When a person is saved into the repository the Map<String, String> properties
is flatten up. As an example, if we have the following object:
Person: {
id := 1;
firstName := John,
lastName := Doe,
properties := {
age: 42
}
}
the document saved in the MongoRepository will be the following:
Person: {
id := 1;
firstName := John,
lastName := Doe,
age := 42
}
Now my problem is that I have to look for objects based on (for example), if they have a specific property or not. Lets say I want all Persons for which an age property has been defined. One important additional requirement is that I should return a paged result.
I've tried using the
findAll(Example<Person> example, Pageable pageable)
But this does not work for some reason. I suspect that it's the fact that my model object and the MongoDB Document have different structures.
I've also tried with the QueryDsl (here you have an example: http://www.baeldung.com/queries-in-spring-data-mongodb) but with no success either, and also to me this solution is not to elegant (having to mantain generated classes and alike. Also I have a feeling it will not work because of my Map<String, String> properties
object member).
Another solution that came to my mind and would be elegant enough, is to have the following function:
@Query(value = "?0")
Page<Query> findByQuery(String query, Pageable pageable)
In this case I would be able to manually construct the query and I wouldn't have to hardcode the key by which I run the search. My question now is, how can set the query value to be exactly my first parameter? With the example showned above I get the following error
java.lang.ClassCastException: java.lang.String cannot be cast to com.mongodb.DBObject
One other solution would be to use mongoTemplate
and query given some Criteria
as in the following example:
final Query query = new Query();
query.addCriteria(Criteria.where("age").regex(".*"));
mongoTemplate. find(query, Person.class);
The problem with this solution is that it returns a list of objects instead for a paged result. It cal also return a specific page if I add query.with(new PageRequest(3, 2));
but in this case I cannot manually construct the "paged" result because I do not know the total number of elements.
Do you have any other ideas that could help me?
Thanks in advance!
There is a realy easiest way to do this, similar to your code:
@Query(value = "?0")
Page<Query> findByQuery(String query, Pageable pageable)
But passing your query as a BSONObject instead of String
@Query("?0")
Page<Query> findByQuery(BSONObject query, Pageable pageable)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With