嵌套 Java Object/Json(Spring 启动)的 CosmosDb 分区键

CosmosDb Partition Key For Nested Java Object/Json (Spring Boot)

我正在尝试根据嵌套的 Java 对象和相应的 Json 对集合进行分区。我知道这样做可能看起来不合理,但我正在做一个开发阶段很长的项目,目前我们客户团队期望的布局并不灵活。示例)名为 receiptItem 的对象的等效 Json 如下所示:

{
   "id": "1",
   "item": { 
      "itemId": "1",
      "name": "itemName",
      "value": 4.98,
      ...
   }, 
   "tax": {
      "rate": 0.15,
      "state": "FL",
      ...
   },
   ...
}

是否可以使用类似于“/item.itemId”的语法在 Azure 中创建分区键?在使用 itemId 作为 receiptItem 集合的分区键时,还有其他方法可以解决这个问题吗?

如果有关于如何在 Azure 中执行此操作的答案,我也有兴趣弄清楚相应的 Java 代码是什么样的。与 C# 不同,@PartitionKey 注释似乎没有指定嵌套对象的属性(如 [ParitionKey(item.id)]),而且我在我的配置中看不到这样做的方法(在 Spring boot) 要么。

在 Java 中,看起来像:

@Data
@NoArgsConstructor
@FullArgsContructor
@ToString
@Document(collection="receiptItems")
public class ReceiptItem {
   @Id
   int id;
   // @PartitionKey???
   Item item;
   Tax tax;
   ...
}

我遇到了类似的问题,我不得不从嵌套中移出分区键。 即使在那之后,我也找不到任何方法让 spring 引导中的 MongoRepository 知道分区键。 我在这里提出了这个问题 - Spring Boot not able to update sharded collection on azure cosmos db(MongoDb)

只要您的对象中存在分区键,正常的插入和提取就可以正常工作。更新和删除查询会失败。

我想出了一个解决方法。我必须自动装配 MongoTemplate 并创建一个基本查询来更新我的对象。

public DocumentDev updateProcessedFlag(DocumentDev request) {
    Query query = new Query();
    query.addCriteria(Criteria.where("_id").is(request.getId()));
    // dNumber is my partition key here.
    query.addCriteria(Criteria.where("dNumber").is(request.getDNumber()));
    Update update = new Update();
    update.set("processed", request.isProcessed());
    mongoTemplate.updateFirst(query, update, request.getClass());
    return request;
}

另一种变体是使用 udate.fromDocument(Document,Exclude) 函数,您可能需要将对象转换为 BSON 文档并像这样使用它。

public DocumentDev updateProcessedFlag(DocumentDev request) {
    // convert your object to document
    Gson gson = new GsonBuilder().create();
    String json = gson.toJson(pojo);
    Document doc = Document.parse(json);

    // create query
    Query query = new Query();
    query.addCriteria(Criteria.where("_id").is(request.getId()));
    query.addCriteria(Criteria.where("dNumber").is(request.getDNumber()));
    Update update = Update.fromDocument(doc,"");
    // run update command using mongoTemplate
    mongoTemplate.updateFirst(query, update, request.getClass());
    return request;
}

如果有什么方法可以告诉 spring 启动分区键。那将是一个更好的解决方案。在此之前,这是我想出的解决方法。

目前肯定可以在 Azure 中使用 'nested' 分区键。例如,/item/id 将用于使 item 中的 id 字段成为分区键。相应的 Json 文档如下所示:

{
   "id": "1",
   "item": { 
      "itemId": "1",
      "name": "itemName",
      "value": 4.98,
      ...
   }, 
   "tax": {
      "rate": 0.15,
      "state": "FL",
      ...
   },
   ...
}

遗憾的是,Spring 目前不支持嵌套分区键。非常感谢 ChrisAnderson-MSFT 参与寻找解决方案,并在 github 上提出问题,可在此处找到:https://github.com/Microsoft/spring-data-cosmosdb/issues/350.