Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Data Mongo Custom Repository Query with ObjectID

I have a mongo query I want to implement as a Spring Mongo Repository

db.collection.find({ 'items': 
    { $elemMatch: { 
        'refund.$id' :  ObjectId('5638cab2e4b07ff212618d7e') 
        } 
    }
}) 

My Repository interface is

@Query("{ 'items': { $elemMatch: { 'refund.$id' :  ObjectId(?0) } } }")
RMA findRMAByItemRefund(String refundId);

It throws JSONParseException

Caused by: com.mongodb.util.JSONParseException: 
{ 'items': { $elemMatch: { 'refund.$id' :  ObjectId("_param_0") } } }
                                       ^
    at com.mongodb.util.JSONParser.parse(JSON.java:216)
like image 881
Whales Avatar asked Nov 19 '15 13:11

Whales


People also ask

How do I create a custom query in Mongo Repository?

We can use the @Query annotation to specify a custom query to declare a method of custom Repository. It works equally well with MongoDB as it does with JPA. However, the only difference is that in case of MongoDB, @Query takes a JSON query string instead of a JPA query.

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.

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.


1 Answers

As the accepted solution did not yield any results in my case, I had to find another solution, that was:

Instead of using the autogenerated query functionality defined via @Query(...) I opted for manually building the DBObject used to query mongo, and defining the functionality as a default implementation in the interface, thus keeping it "clean" (" - because had to introduce a _query method)

Note: This solution only works in Java 1.8+

public interface SomeRepository extends MongoRepository<SomeEntity, String> {

    @Query("{'nestedEntity._id': ?0}")
    SomeEntity findByNestedEntityId_DoesntWork(String nestedEntityId);

    @Query("?0")
    SomeEntity _query(DBObject query);

    default SomeEntity findByNestedEntityId(String nestedEntityId) {
        DBObject queryObject = BasicDBObjectBuilder
            .start("nestedEntity._id", new ObjectId(nestedEntityId))
            .get();

        return this._query(queryObject);
    }
}
like image 127
Matyas Avatar answered Sep 19 '22 13:09

Matyas