【问题标题】:Upsert Mongo Document using spring data mongo使用 spring data mongo 插入 Mongo 文档
【发布时间】:2016-05-15 04:51:12
【问题描述】:

我有一个班级

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

我添加了带有 @EnableMongoAuditing 注释的应用程序

我已经创建了实现 mongorepository 的接口

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

当我使用 GET,POST,PATCH 方法创建 RestController 在POST 我正在发送 {'title':'first'}

Controller 类的 POST 方法是

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

它将数据保存在 mongo 中。

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

PATCH 请求就像

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

在使用数据{"description":"This is test"} 发出 PATCH 请求时 它更新了文档 BUT 它从文档中删除了标题字段和 createdDate ,它进行更新是可以的。但我想做一个 upsert,我可以使用 mongoTemplate, 但是我必须设置我想要设置的每个属性。

如果我收到 PATCH 请求,是否有任何通用方法,我只能更新不为空的属性.. 请求中的属性

spring-data-rest 似乎使用@RepositoryRestResource 来做到这一点。我怎样才能做到这一点。

我不想这样编码 Update update = new Update().set("title", myDocument.getTitle()).set("description", myDocument.getdescription());

【问题讨论】:

  • 你的 courseService.save(myDocument) 函数在做什么?
  • 运气好吗?我一直在寻找相同问题的解决方案。

标签: spring spring-boot spring-data spring-data-mongodb spring-data-rest


【解决方案1】:

不幸的是它在 MongoDB 中的行为,您可以使用 shell 验证相同的行为。 所以要更新创建一个更新对象并使用

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

这里的 ID 是您要更新的文档。根据您的要求设置 upsert 之后使用 findAndModify 更新文档。

mongoTemplate.findAndModify(query, update,
                new FindAndModifyOptions().returnNew(true).upsert(false),
                someclass.class);

【讨论】:

    【解决方案2】:

    如果你有一个像 MyModel.class 这样的模型,并且你需要一种平滑的方法来从中创建一个更新对象,那么没有真正明确的方法来做到这一点,但是你可以使用在 Spring Data Mongo 自动配置中创建的 MongoConverter bean然后只需使用 MongoCollection 的 replaceOne 方法。

    @Autowired
    private MongoTemplate template;
    @Autowired
    private MongoConverter mongoConverter;
    
    ...
    
    @Override
    public void upsertMyModel(MyModel model) {
        Document documentToUpsert = new Document();
        mongoConverter.write(model, documentToUpsert);
        template.getCollection(collectionName).replaceOne(
                Filters.eq("_id", model.getId()),
                documentToUpsert,
                new ReplaceOptions().upsert(true));
    }
    

    【讨论】:

      【解决方案3】:

      Upsert 可以使用 BulkOperations 在 Spring 数据 mongodb 中完成。 假设有两个实体 Entity1 和 Entity2。 Entity1 有foreginId,它是Entity2 的主要id。两者都有一个字段title。现在,从 entity2 到 entity1 的 upsert,我们可以这样做:

      Query query = new Query(Criteria.where("foreignId").is(entity2.getId()));
      Update update = new Update();
      update.set("title",entity2.getTitle());
      List<Pair<Query, Update>> updates = new ArrayList<Pair<Query, Update>>();
      updates.add(Pair.of(query, update););
      BulkOperations bulkOps = this.mongoTemplate.bulkOps(BulkMode.UNORDERED, Entity1.class);
      bulkOps.upsert(updates);
      bulkOps.execute();
      

      【讨论】:

        猜你喜欢
        • 2014-05-15
        • 1970-01-01
        • 2017-03-15
        • 1970-01-01
        • 2016-07-11
        • 2020-09-22
        • 2022-01-14
        • 2018-06-16
        • 1970-01-01
        相关资源
        最近更新 更多