0

在 MongoDB 中,我有一个名为 Customer 的文档集合,其中嵌入了客户定义的标签。我的域对象看起来像这样(包括 Lombok 注释):

@Document(collection = "Customer")
@Getter
@Setter
public class Customer {
    @Id
    long id;

    @Field("name")
    String name;

    @Field("labels")
    List<CustomerLabel> labels;
}

@Getter
@Setter
public class CustomerLabel {

    @Id
    @Field("label_id")
    long labelId;

    @Field("label_name")
    String labelName;
}

现在,对的响应GET /customers如下所示:

{
  "_links": {
    "self": {
      "href": "http://localhost:8080/app/customers?page=&size=&sort="
    }
  },
  "_embedded": {
    "customers": [
      {
        "name": "Smith, Jones, and White",
        "labels": [
          {
            "labelName": "General label for Smith, Jones, and White"
          }
        ],
        "_links": {
          "self": {
            "href": "http://localhost:8080/app/customers/285001"
          }
        }
      }
    ]
  },
  "page": {
    "size": 20,
    "totalElements": 1,
    "totalPages": 1,
    "number": 0
  }
}

我想将嵌入标签文档“调用”为单独的链接关系,以便响应GET /customers看起来更像这样:

{
  "_links": {
    "self": {
      "href": "http://localhost:8080/app/customers?page=&size=&sort="
    }
  },
  "_embedded": {
    "customers": [
      {
        "name": "Smith, Jones, and White",
        "_links": [
          {
          "labels": {
            "href": "http://localhost:8080/app/customers/285001/labels"
          },
          {
          "self": {
            "href": "http://localhost:8080/app/customers/285001"
          }
        }]
      }
    ]
  },
  "page": {
    "size": 20,
    "totalElements": 1,
    "totalPages": 1,
    "number": 0
  }
}

我怎样才能在我的应用程序中做到这一点?

4

2 回答 2

0

我最终实现了一个从 Repository REST 控制器返回ResourceProcessor的对象中删除标签的方法。Resource它看起来像这样:

@Controller
@AllArgsConstructor(onConstructor = @__(@Inject))
class CustomerResourceProcessor implements ResourceProcessor<Resource<Customer>> {

    private final @NonNull CustomerLinks customerLinks;

    @Override
    public Resource<Customer> process(Resource<Customer> resource) {
        Customer customer = resource.getContent();
        if (customer.getLabels() != null && !customer.getLabels().isEmpty()) {
            resource.add(customerLinks.getLabelCollectionLink(resource));
            customer.setLabels(null);
        }
        return resource;
    }
}

然后我LabelController以我见过的 RESTBucks 示例的方式编写了一个:

@ResponseBody
@RequestMapping(value = "/customers/{customerId}/labels", method = RequestMethod.GET)
Resources<LabelResource> labels(@PathVariable Long customerId) {
    List<CustomerLabel> customerLabels = customerRepository.findLabelsByCustomerId(customerId);
    return new Resources<>(resourceAssembler.toResources(customerLabels), linkTo(
            methodOn(this.getClass()).labels(customerId)).withSelfRel());
}

上面的findLabelsByCustomerId方法CustomerRepository是一个自定义的存储库方法实现,它只返回labels来自 Mongo 的字段。

用最少的代码就可以很好地工作。诀窍是弄清楚我需要编写哪些代码。:)

于 2014-06-17T05:26:28.033 回答
0

我认为,这是一种次优设计。使用 MongoDB 时,您建模的文档基本上是领域驱动设计术语中的聚合,因为概念很好地对齐(接受相关聚合/文档等之间的最终一致性)。

存储库模拟聚合的集合(读取:文档,在 MongoDB 中)的情况。因此,拥有嵌入式文档的存储库(CustomerLabel在您的情况下)实际上并没有太大意义。此外,将Customers 和 s都保存CustomerLabels到同一个集合中,但也让前者嵌入后者对我来说看起来很可疑。

所以这似乎更像是一个 MongoDB 模式设计问题,而不是关于如何通过 Spring Data 公开文档的问题。也就是说,我不太确定你真的会得到一个令人满意的答案——正如我所指出的——你提出的问题似乎掩盖了你的代码库中一个更根本的挑战。

于 2014-06-15T08:35:09.927 回答