当修改后的字段不总是相同时,如何更新MongoDB文档的字段?

时间:2020-07-16 10:43:23

标签: java mongodb jax-rs quarkus quarkus-panache

假设我有一个Foo类和一个向CRUD Foos公开API的jax-rs FooResource。

Foo代表MongoDB文档。

在FooResource中,我会遇到这样的事情:

@PATCH
@Path("{id}")
public Response update(@PathParam("id") ObjectId id, Foo foo) {
    return Response.ok(fooService.update(id, foo)).build();
}

问题在于json中的foo对象将仅包含已更改的字段,但我永远不知道它会是什么字段。

我使用带有Panache扩展名的Quarkus,我看到的唯一方法是从数据库中检索实体,然后检查从http请求收到的foo对象中的每个字段,以查看它是否为null,以及如果没有,请在实体中设置新值,最后在其上调用update()。

但是,如果我有一堂课涉及很多领域,那将成为一场噩梦。 这是一个非常常见的用例,我无法想象(或不想相信)这是实现此目的的唯一方法。

如果有一种方法可以将不完整的文档发送到MongoDB,以便仅更改此文档中存在的字段,那将是完美的。但是我没有找到一种方法。既不使用quarkus(有或没有panache),也没有使用mongo API的Java驱动程序。

那么有没有更简单的方法可以做到这一点?我更喜欢使用带有Panache扩展名的quarkus MongoDB的解决方案,但是没有Panache甚至直接使用Java驱动程序API的解决方案也是可以的。

PS:从前端发送完整对象并替换整个文档对我来说不是一个选择。

谢谢。

1 个答案:

答案 0 :(得分:1)

您可以使用update(updateDocument, updateParams).where(query, params)方法,它提供了更灵活的更新方法。

来自文档指南的示例:

// set the name of all living persons to 'Mortal'
long updated = Person.update("name", "Mortal").where("status", Status.Alive);

对于您的用例,查询部分位于_id字段上,但是您仍然需要根据Foo对象的字段存在情况来动态构建更新部分。

正如您所说,没有办法轻松地做到这一点,因为Java客户端就像您使用类型化集合(集合绑定到Java类型而不是Document时一样)应该将空值字段反映为数据库(MongoDB客户端如何知道null表示有时不更新该字段或将该字段更新为null)。

因此对于此用例,您可以:

  • 使用所需字段伪造一个更新Document(这就是“ update(updateDocument,updateParams).where(query,params)`为您做的事情。)
  • 首先获取实体,将其手动合并(您可以轻松地为其创建基于反射的帮助器),然后对其进行更新。