Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Repository query with a List parameter in Spring Data MongoDB

I have the following POJO.

@Document(collection = "questions") public class Question {      @Id     private String id;      public List<String> getTags() {         return tags;     }      public void setTags(List<String> tags) {         this.tags = tags;     } } 

I am trying to implement a MongoRepository query which finds all Questions that contain a list of tags. I have tried the following:

@Repository public interface QuestionRepository extends MongoRepository<Question, String> {     List<Question> findByTags(List<String> tags); } 

but this is only working when the List of tags that I'm passing to the method fully matches the list of tags assigned to the question in Mongo. E.g. if I have a question in Mongo with a list of tags [ "t1", "t2", "t3" ] it is not returned by findByTags(List) when I pass [ "t1", "t2" ] to the method.

I have tried the following as well:

@Repository public interface QuestionRepository extends MongoRepository<Question, String> {     @Query("{ tags: { $all: ?0 } }")     List<Question> findByTags(List<String> tags); } 

but then my war could not be deployed to my servlet container at all. (I get the following error in that case:

The web application [backend] appears to have started a thread named [cluster-1-db:27017] but has failed to stop it. This is very likely to create a memory leak. 

Would you please advise on how to implement that custom query?

like image 334
Marchev Avatar asked May 08 '15 12:05

Marchev


People also ask

What is the difference between MongoOperations and MongoTemplate?

MongoTemplate provides a simple way for you to save, update, and delete your domain objects and map those objects to documents stored in MongoDB. You can save, update and delete the object as shown below. MongoOperations is the interface that MongoTemplate implements.

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.

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.

Can I use Spring data JPA with MongoDB?

Yes, DataNucleus JPA allows it, as well as to many other databases.


2 Answers

I will answer my own question as I have just found the answer by myself. The following section in the Spring Data MongoDB documentation lists all supported keywords that are used by Spring for its query derivation:

http://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#repository-query-keywords

The following implementation works for the use case described above:

@Repository public interface QuestionRepository extends MongoRepository<Question, String> {      List<Question> findByTagsIn(List<String> tags); } 
like image 125
Marchev Avatar answered Oct 05 '22 13:10

Marchev


The CONTAINING keyword may also be used:

@Repository public interface QuestionRepository extends MongoRepository<Question, String> {      List<Question> findByTagsContaining(List<String> tags); } 

example and how it's mongo query looks like:

findByAddressesContaining(Address address)  {"addresses" : { "$in" : address}} 

This can also accept list of address in params.

See documentation: https://github.com/spring-projects/spring-data-mongodb/blob/e28bede416e4ddac19a35dc239388afc90b9cac4/src/main/asciidoc/reference/mongo-repositories.adoc

like image 25
alegria Avatar answered Oct 05 '22 11:10

alegria