【问题标题】:CosmosDb Partition Key For Nested Java Object/Json (Spring Boot)嵌套 Java 对象/Json (Spring Boot) 的 CosmosDb 分区键
【发布时间】:2019-08-05 16:10:27
【问题描述】:

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

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

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

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

在 Java 中,看起来像:

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

【问题讨论】:

  • 您不能将数组中的项目用作分区键的一部分。我建议只在您的对象上创建一个名为“partitionKey”的新属性,并将其设置为您想要的值。缺点是您复制了数据,但您可以保持架构不变。
  • 好吧,我担心会是这样。感谢您的评论。
  • 再想一想,我不知道为什么我什至有括号,因为我的实际代码中的类不是一个集合。我将编辑问题并继续等待答案。
  • 我将跟进如何使用 Spring Data 连接器执行此操作。我们应该为此发布一个样本。您可以通过将分区键路径设置为“/item/itemId”从门户/模拟器 UI 创建集合来实现它,但我不确定这是否适用于 Spring。我会让春天的人给我们一个答案。
  • 看起来 Spring 尚不支持在子对象上声明分区键,因此您现在必须通过 cli/portal/sql sdk 预先创建它才能使用嵌套类型。我创建了一个问题来帮助跟踪:github.com/Microsoft/spring-data-cosmosdb/issues/350

标签: azure azure-cosmosdb database-partitioning document-database azure-cosmosdb-tables


【解决方案1】:

我遇到了类似的问题,我不得不从巢中移出我的分区键。 即使在那之后,我也找不到任何方法让 Spring Boot 中的 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 boot 分区键。那将是一个更好的解决方案。在那之前,这是我想出的解决方法。

【讨论】:

  • 到目前为止,我能够完成所有基本的 CRUD/DocumentDbRepository 操作。问题是我没有使用最适合我的数据的分区键,随着用户/请求数量的增加,这一点越来越受到关注。不过感谢您的回答。
【解决方案2】:

目前当然可以在 Azure 中使用“嵌套”分区键。例如,/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。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-02
    • 2016-03-01
    • 1970-01-01
    相关资源
    最近更新 更多