Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Upsert Mongo Document using spring data mongo

I have a Class

@Document
public class MyDocument {
   @Id
   private String id;
   private String title;
   private String description;
   private String tagLine;

   @CreatedDate
   private Date createdDate;

   @LastModifiedDate
   private Date updatedDate;

   public String getId() {
     return id;
   }
   public void setId(String id) {
     this.id = id;
   }

   public String getTitle() {
     return title;
   }

   public void setTitle(String title) {
     this.title = title;
   }

   public String getDescription() {
     return description;
   }

  public void setDescription(String description) {
    this.description = description;
  }
  public String getTagLine() {
     return tagLine;
   }

  public void setTagLine(String tagLine) {
    this.tagLine = tagLine;
  }
}

i have added annotated application with @EnableMongoAuditing

i have created interface which implements mongorepository

public interface MyDocumentRepository extends MongoRepository<MyDocument, String> { }

when i have created RestController with GET,POST,PATCH methods in POST I'm sending {'title':'first'}

Controller Class POST method is

@RequestMapping(value = "/", method = RequestMethod.POST)
public ResponseEntity<?> saveMyDocument(@RequestBody MyDocument myDocument) { 
   MyDocument doc = myDocumentRepo.save(myDocument);
   return new ResponseEntity<MyDocument>(doc, HttpStatus.CREATED);
}

Its saving the data in mongo.

{
    "_id" : ObjectId("56b3451f0364b03f3098f101"),
    "_class" : "com.wiziq.service.course.model.MyDocument",
    "title" : "test"
}

and PATCH request is like

@RequestMapping(value = "/{id}", method = RequestMethod.PATCH)
public ResponseEntity<MyDocument> updateCourse(@PathVariable(value = "id") String id,
        @RequestBody MyDocument myDocument) {
    myDocument.setId(id);
    MyDocument doc = courseService.save(myDocument);
    return ResponseEntity.ok(course);
}

when in make PATCH request with data {"description":"This is test"} it update the docuent BUT it removes title field and createdDate form the document, its doing update which is ok. But i wanted to do an upsert, i can do its using mongoTemplate, but there i have to set each property which i want to set.

Is there any generic way to that if i get a PATCH request i can update only not null properties.. properties which are coming in request

spring-data-rest seems to do it using @RepositoryRestResource. How can i achieve the same.

I don't want to code like this Update update = new Update().set("title", myDocument.getTitle()).set("description", myDocument.getdescription());

like image 343
Dinkar Thakur Avatar asked Feb 05 '16 09:02

Dinkar Thakur


People also ask

How does Upsert work in MongoDB?

Here in MongoDB, the upsert option is a Boolean value. Suppose the value is true and the documents match the specified query filter. In that case, the applied update operation will update the documents. If the value is true and no documents match the condition, this option inserts a new document into the collection.

Can we use Spring data JPA with MongoDB?

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

Which is better MongoTemplate or MongoRepository?

So I'd say that MongoTemplate is a better option, unless you have a very elaborated POJO model or need the custom queries capabilities of MongoRepository for some reason. Good points/examples. However your race condition example and undesired result can be avoided using @Version to prevent that very scenario.


1 Answers

Unfortunately its the behavior in MongoDB, you can verify the same using shell. So to update create an Update Object and using

Query query = new Query(Criteria.where("id").is(ID)); 

Here ID is the document which you want to update.Based on your requirement set upsert after that using findAndModify update document.

mongoTemplate.findAndModify(query, update,
                new FindAndModifyOptions().returnNew(true).upsert(false),
                someclass.class);
like image 105
rajadilipkolli Avatar answered Sep 29 '22 09:09

rajadilipkolli