SpringData Mongo projection ignore and overide the values on save

Viewed 439

Let me explain my problem with SpringData mongo, I have the following interface declared, I declared a custom query, with a projection to ignore the index, this example is only for illustration, in real life I will ignore a bunch of fields.

public interface MyDomainRepo extends MongoRepository<MyDomain, String> {
    @Query(fields="{ index: 0 }")
    MyDomain findByCode(String code);
}

In my MongoDB instance, the MyDomain has the following info, MyDomain(code="mycode", info=null, index=19), so when I use the findByCode from MyDomainRepo I got the following info MyDomain(code="mycode", info=null, index=null), so far so good, because this is expected behaviour, but the problem happens when..., I decided to save the findByCode return.

For instance, in the following example, I got the findByCode return and set the info property to myinfo and I got the object bellow.

MyDomain(code="mycode", info="myinfo", index=null)

So I used the save from MyDomainRepo, the index was ignored as expected by the projection, but, when I save it back, with or without an update, the SpringData Mongo, overridden the index property to null, and consequently, my record on the MongoDB instance is overridden too, the following example it's my MongoDB JSON.

{
    "_id": "5f061f9011b7cb497d4d2708",
    "info": "myinfo",
    "_class": "io.springmongo.models.MyDomain"
}

There's a way to tell to SpringData Mongo, to simply ignores the null fields on saving?

1 Answers
  • Save is a replace operation and you won't be able to signal it to patch some fields. It will replace the document with whatever you send

  • Your option is to use the extension provided by Spring Data Repository to define custom repository methods

    public interface MyDomainRepositoryCustom {
 
      void updateNonNull(MyDomain myDomain);
 
    }
   public class MyDomainRepositoryImpl implements MyDomainRepositoryCustom {
 
     private final MongoTemplate mongoTemplate;
 
     @Autowired
     public BookRepositoryImpl(MongoTemplate mongoTemplate) {
        this.mongoTemplate = mongoTemplate;
     }
 
     @Override
     public void updateNonNull(MyDomain myDomain) {
        //Populate the fileds you want to patch
        Update update = Update.update("key1", "value1")
                              .update("key2", "value2");

        // you can you Update.fromDocument(Document object, String... exclude) to
        // create you document as well but then you need to make use of `MongoConverter`  
        //to convert your domain to document. 

        // create `queryToMatchId` to mtach the id
        mongoTemplate.updateFirst(queryToMatchId, update, MyDomain.class);
     }
 
    }
    public interface MyDomainRepository extends MongoRepository<..., ...>, 
                                            MyDomainRepositoryCustom {
    }
Related