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

How to update document in mongo to get performance?

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

我尝试了以下方式,在我的情况下效果很好,但我不确定这是 correct/Best/Advisable 就性能而言更新等的方式。

有人可以指导一下吗?

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

您可以使用 mongo 文档中所述的更新插入功能。 https://docs.mongodb.com/v3.2/reference/method/db.collection.update/

您将不得不使用 MongoTemplate.upsert() 来实现此目的。 您将需要再添加两个 classes:StudyRepositoryCustom,这是一个 interface 和一个 class 扩展此接口,例如 StudyRepositoryImpl

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

将您当前的 StudyRepository 更新为 extend 这个 interface

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

并添加实现 StudyRepositoryCustom 的 class。这是我们将 @Autowire 我们的 MongoTemplate 并提供更新 Study 或在它不存在时保存它的实现。我们使用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 数据基础架构获取,因为我们遵循了使用 Impl[= 扩展核心存储库接口名称的命名约定30=]

检查 github 上的 this 示例,用于 @Autowire-ing a MongoTemplate 并如上所述使用自定义存储库。

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

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

这里有更多信息https://docs.mongodb.com/manual/reference/method/db.collection.save/

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

简化域Object:

@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

的记录

Collection之前的状态:

{
        "_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);

    }

Collection 之后的状态:

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