How to update document in mongo to get performance?

杀马特。学长 韩版系。学妹 提交于 2020-01-02 04:06:08

问题


I am new to Spring Data Mongo. I've a scenario where I want to create a Study if already not present in mongo db. If its already present, then I've to update it with the new values.

I tried in the following way, which works fine in my case, but I'm not sure this is the correct/Best/Advisable way to update etc as far as performance is concerned.

Could anyone please guide on this?

public void saveStudy(List<Study> studies) {
        for (Study study : studies) {
            String id = study.getId();
            Study presentInDBStudy = studyRepository.findOne(id);

            //find the document, modify and update it with save() method.
            if(presentInDBStudy != null) {
                presentInDBStudy.setTitle(task.getTitle());
                presentInDBStudy.setDescription(study.getDescription());    
                presentInDBStudy.setStart(study.getStart());
                presentInDBStudy.setEnd(study.getEnd());
                repository.save(presentInDBStudy);
            }
            else
                repository.save(study);
        }
    }

回答1:


You will have to use the MongoTemplate.upsert() to achieve this. You will need to add two more classes: StudyRepositoryCustom which is an interface and a class that extends this interface, say StudyRepositoryImpl

interface StudyRepositoryCustom {
   public WriteResult updateStudy(Study study);
}

Update your current StudyRepository to extend this interface

@Repository
public interface StudyRepository extends MongoRepository<Study, String>, StudyRepositoryCustom {
   // ... Your code as before
}

And add a class that implements the StudyRepositoryCustom. This is where we will @Autowire our MongoTemplate and provide the implementation for updating a Study or saving it if it does not exist. We use the MongoTemplate.upsert() method.

class StudyRepositoryImpl implements StudyRepositoryCustom {
   @Autowired
   MongoTemplate mongoTemplate;

   public WriteResult updateStudy(Study study) {
      Query searchQuery = new Query(Criteria.where("id").is(study.getId());
      WriteResult update = mongoTemplate.upsert(searchQuery, Update.update("title", study.getTitle).set("description", study.getDescription()).set(...)), Study.class);
      return update;
   }
}

Kindly note that StudyRepositoryImpl will automatically be picked up by the Spring Data infrastructure as we've followed the naming convention of extending the core repository interface's name with Impl

Check this example on github, for @Autowire-ing a MongoTemplate and using custom repository as above.

I have not tested the code but it will guide you :-)




回答2:


You can use upsert functionality for this as described in mongo documentation. https://docs.mongodb.com/v3.2/reference/method/db.collection.update/




回答3:


You can update your code to use <S extends T> List<S> save(Iterable<S> entites); to save all the entities. Spring's MongoRepository will take care of all possible cases based on the presence of _id field and its value.

More information here https://docs.mongodb.com/manual/reference/method/db.collection.save/

This will work just fine for basic save operations. You don't have to load the document for update. Just set the id and make sure to include all the fields for update as it updates by replacing the existing document.

Simplified Domain Object:

@Document(collection = "study")
public class Study {
    @Id
    private String id;
    private String name;
    private String value;
}

Repository:

public interface StudyRepository extends MongoRepository<Study, String> {}

Imagine you've existing record with _id = 1

Collection state before:

{
        "_id" : 1,
        "_class" : "com.mongo.Study",
        "name" : "saveType",
        "value" : "insert"
}

Run all the possible cases:

public void saveStudies() {
        List<Study> studies = new ArrayList<Study>();

        --Updates the existing record by replacing with the below values.
        Study update = new Study();
        update.setId(1);
        update.setName("saveType");
        update.setValue("update");

        studies.add(update);

        --Inserts a new record.
        Study insert = new Study();
        insert.setName("saveType");
        insert.setValue("insert");

        studies.add(insert);

        --Upserts a record.
        Study upsert = new Study();
        upsert.setId(2);
        upsert.setName("saveType");
        upsert.setValue("upsert");

        studies.add(upsert);

        studyRepository.save(studies);

    }

Collection state after:

{
        "_id" : 1,
        "_class" : "com.mongo.Study",
        "name" : "saveType",
        "value" : "update"
}
{
        "_id" : 3,
        "_class" : "com.mongo.Study",
        "name" : "saveType",
        "value" : "insert"
}
{
        "_id" : 2,
        "_class" : "com.mongo.Study",
        "name" : "saveType",
        "value" : "upsert"
}


来源:https://stackoverflow.com/questions/40534212/how-to-update-document-in-mongo-to-get-performance

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!