【问题标题】:Spring reactive mongodb template update document partially with objectsSpring响应式mongodb模板更新文档部分包含对象
【发布时间】:2018-09-23 07:18:06
【问题描述】:

我有一些类(文档)要在 mongo db 中更新

mongo中存储的文档(实际例子比较复杂):

{
   "id": "5ba6b0576cba836aa43ab379",
   "firstName": "First Name",
   "lastName": "Last Name",
   "mobile": "123456789"
   ....................
   ....................
   ....................
   "address": "some address"
}

假设我有上面所有这些字段的类 Foo。

我从外部部分对象收到(Foo 只有 3 个值,所有其他值为 null),例如:

{
   "id": "5ba6b0576cba836aa43ab379",
   "mobile": "987654321",
   "address": "other address"
}

我想更新文档,但只有收到的字段。

我发现只有使用 reactivemongotemplate 手动执行此操作的选项。 我正在寻找更“好”的方式,而无需手动创建更新对象。比如:

reactivemongotemplate.updateFirst(
    Query.query(Criteria.where("id").is("5ba6b0576cba836aa43ab379")), 
    partialFoo // (object of class is Foo)
)

有人知道怎么做吗?

【问题讨论】:

    标签: mongodb spring-boot spring-data


    【解决方案1】:

    我不知道这是否是“最好”的方法,但是对于我开始的休息网络服务,我一直在尝试在内部简化 PATCH 和 PUT 方法,我使用 Map使用org.apache.commons.beanutils.PropertyUtils 库,然后创建要传递给ReactiveMongoTemplate 的更新对象,或多或少像这样:

    Map<String, Object> changes = PropertyUtils.describe(myDto);
    // ... check the fields that must be sets and other business rules ...
    Update updateFields = new Update();
    for(Map.Entry<String, Object> entry : changes.entrySet()){
      updateFields.set(entry.getKey(), entry.getValue());
    }
    reactivemongotemplate.updateFirst(query(where("id").is(myId)), updateFields, MyEntity.class)
    

    这意味着您的 MyDto 类具有您需要的每个字段的 getter 和 setter,但到目前为止它运行良好。

    【讨论】:

    • 谢谢,我自己实现了类似的解决方案,但我肯定会替换为 PropertyUtils 以删除我自己的代码。
    • 我很高兴它有帮助 ;-)
    【解决方案2】:

    这就是我对这种情况的解决方案

      public Mono<ProjectChild> UpdateCritTemplChild(
           String id, String idch, String ownername) {
    
        Query query = new Query();
        query.addCriteria(Criteria.where("_id")
                                  .is(id));
        query.addCriteria(Criteria.where("tasks._id")
                                  .is(idch));
    
        Update update = new Update();
        update.set("tasks.$.ownername", ownername);
    
        return template
             // findAndModify:
             // Find/modify/get the "new object" from a single operation.
             .findAndModify(
                  query, update,
                  new FindAndModifyOptions().returnNew(true), ProjectChild.class
                           )
             ;
    
      }
    

    【讨论】:

    • 我认为,主要的一点是能够仅在给定对象的情况下编辑部分文档,而无需手动设置所有字段。您的示例适用于单个字段更改,但如果有几十个,或者如果字段是动态的,则可能无法使用您的解决方案。
    猜你喜欢
    • 2015-02-22
    • 1970-01-01
    • 1970-01-01
    • 2022-07-23
    • 1970-01-01
    • 2012-05-18
    • 2021-02-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多