Search code examples
javamongodbrepositoryspring-mongodbspring-repositories

MongoDB and Spring Boot - Best way to update a Document?


I have the following Java POJO in my spring boot application:

    public class Round {

        private ObjectId _id;

        @NotEmpty
        @Getter
        @Setter
        @Accessors(fluent = true)
        @JsonProperty("userId")
        private String userId;

        @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy")
        @JsonDeserialize(using = LocalDateDeserializer.class)
        @JsonSerialize(using = LocalDateSerializer.class)
        @Getter
        @Setter
        @Accessors(fluent = true)
        @JsonProperty("date")
        private LocalDate date;

        @Min(value = 1, message = "Score should not be less than 1")
        @Getter
        @Setter
        @Accessors(fluent = true)
        @JsonProperty("score")
        private int score;

        // rest of fields

}

I have the following MongoRepository:

@Repository
public interface RoundRepository extends MongoRepository<Round, String> {

    List<Round> findByUserId(String userId);

    @Query("{'userId' : ?0 , '_id' : ?1}")
    Optional<Round> findByUserIdAnd_id(String userId, ObjectId _id);

}

In my Service class I have a working create() and I am trying to implement an update() method to be used with the PUT mapping in my controller:

public Round create(String userId, @Valid @NotNull @RequestBody Round round) {

    // set userId from path
    round.userId(userId);

    roundRepository.save(round);
    return round;
}

public void put(String userId, ObjectId objectId, Round updatedRound) {

    // get original round
    Optional<Round> round = roundRepository.findByUserIdAnd_id(userId, objectId);

    //todo - how to implement PUT in mongo to update to "updatedRound"?

}

I am relatively new to MongoDB, is there a set way to do this? I.e. keep the same ObjectId etc but update other fields in the document?


Solution

  • Note : The following code is not tested, but it gives you an idea well. There are two scenarios.

    1. If you don't send the id with your request, the data will be inserted.
    2. If you send the existing id with your request, the data will be updated.

    Annotate @Id private ObjectId _id; in your entity class

    Controller

    @RestController
    @RequestMapping("YOUR_URL")
    public class RoundController{
    
        @PostMapping("YOUR_URL")
        public ResponseEntity<Round> update(@Valid @RequestBody Round updateRound, BindingResult result){
    
            //Bindning Error handle
             if (bindingResult.hasErrors()) {
                List<String> errors = new ArrayList<>();
                for (ObjectError res : bindingResult.getFieldErrors()) {
                    errors.add(res.getDefaultMessage());
                }
    
                throw new RuntimeError(errors.toString());
            }
            return new ResponseEntity<>(roundService.save(updateRound), HttpStatus.OK);
        }
    }
    

    Repository

    interface RoundRepository extends MongoRepository<Round, ObjectId> {
    }
    

    Service

    interface RoundService {
        Round save(Round round);
    }
    

    Service Implementation

    @Service
    public RoundServiceImpl implements RoundService{
        @Autowired
        RoundRepository repository;
    
        @Override
        public Round save(Round round){
            repository.save(round);
        }
    }
    

    You don't need to actually perform a special query. But if you need to do some logic.

    @Override
    public Round save(Round round){
    
        if(round.get_id()!=null){
            //update logic
        }else {
            // insert logic
        }
    
        repository.save(round);
    }