首页 > 解决方案 > 当修改的字段并不总是相同时,如何更新 MongoDB 文档的字段?

问题描述

假设我有一个 Foo 类和一个将 API 公开给 CRUD Foos 的 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 对象中的每个字段,看看它是否为空,如果不是,在实体中设置新值,最后调用 update() 。

但是,如果我的课程有几十个领域,那将成为一场噩梦。这是一个如此常见的用例,我无法想象(或不想相信)这是做到这一点的唯一方法。

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

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

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

谢谢。

标签: javamongodbjax-rsquarkusquarkus-panache

解决方案


您可以使用该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)` 为你做的)。
  • 首先获取实体,手动合并它(您可以轻松地为此创建基于反射的帮助器),然后更新它。

推荐阅读