如何在mongo中更新文档以获得性能?

时间:2016-11-10 18:01:58

标签: mongodb spring-data-mongodb

我是 Spring Data Mongo 的新手。我有一个场景,我想创建一个研究,如果已经不存在于mongo db中。如果它已经存在,那么我将使用新值更新它。

我尝试了以下方式,在我的情况下工作得很好,但就性能而言,我不确定这是更正等的正确/最佳/建议方式。

有人可以请指导吗?

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);
        }
    }

3 个答案:

答案 0 :(得分:2)

您必须使用MongoTemplate.upsert()来实现此目的。 您需要再添加两个类:StudyRepositoryCustom这是一个interface和一个扩展此界面的类,比如StudyRepositoryImpl

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

将您当前的StudyRepository更新为extendinterface

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

添加一个实现StudyRepositoryCustom的类。这是我们@Autowire我们MongoTemplate的所在位置,并提供更新Study的实施方案,或者如果不存在则保存。{1}}。我们使用MongoTemplate.upsert()方法。

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;
   }
}

请注意,StudyRepositoryImpl将自动被Spring Data基础架构选中,因为我们遵循了使用Impl扩展核心存储库接口名称的命名约定

检查github上的this示例,@Autowire - MongoTemplate并使用上面的自定义存储库。

我没有测试过代码,但它会指导您: - )

答案 1 :(得分:1)

您可以使用mongo文档中描述的upsert功能。 https://ng-bootstrap.github.io/#/components/modal

答案 2 :(得分:1)

您可以更新代码以使用<S extends T> List<S> save(Iterable<S> entites);保存所有实体。 Spring的MongoRepository将根据_id字段及其值的存在来处理所有可能的情况。

此处提供更多信息https://docs.mongodb.com/manual/reference/method/db.collection.save/

这对基本的保存操作很有用。您不必加载文档以进行更新。只需设置id并确保通过替换现有文档来包含所有要更新的字段。

简化域对象:

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

存储库:

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

想象一下,你现有_id = 1

的记录

之前的收集状态:

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

运行所有可能的案例:

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);

    }

收集后状态:

{
        "_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"
}