如何在 Spring 引导中为 CosmosDb 设置分区键

How do I set a Partition Key for CosmosDb in Spring Boot

答案似乎很明显,但我已经尝试了多种注释和配置的组合,但无法找到一种在所有情况下都适用的方法(例如执行 CRUD、DocumentDbRepository 和自定义方法的能力)。

注释示例:

@Data
@...
@Document(collection="items")
public class Item {
   @Id
   private String itemId;
   @PartitionKey
   private String storeNumber;
   ...
}

配置示例:

...
    public DocumentClient config() {
      DocumentClient client = new DocumentClient(
            uri, key, getConnectionPolicy(), ConsistencyLevel.Session);

        client.readDatabases(new FeedOptions()).getQueryIterator().forEachRemaining(database -> {
            System.out.println("Spring database link = " + database.getSelfLink());
        });

        /*
        DocumentCollection coll = new DocumentCollection();
        coll.setId("itemId");
// Corrected based on Sajeetharan's answer:
        PartitionKeyDefinition partitionKeyDefinition = new  PartitionKeyDefinition();
        Collection<String> paths = new ArrayList<>();
        partitionKeyDefinition.setPaths(paths);
        paths.add("storeNumber");
        coll.setPartitionKey(partitionKeyDefinition);
        coll.setResourceId("items");

        // OR

        RequestOptions options = new RequestOptions();
        options.setPartitionKey(new PartitionKey("clubNumber"));

        try {
            client.createCollection(String.format("/dbs/%s", DATABASE), coll, options);
        } catch (DocumentClientException e) {
            e.printStackTrace();
        }
        */

        return client;
    }
...

到目前为止,当我让 Microsoft 为我处理分区键并指定 @Id 字段和客户端配置时,我的代码可以正常工作。但是,在这种情况下,我想使用特定的分区键。上面的例子只是我为了让它工作而尝试实施的不同组合的一小部分。尽管如此,我还是要结束像这样的例外:java.lang.UnsupportedOperationException: PartitionKey value must be supplied for this operation 对于像 findById() 这样简单的东西。话虽如此,我将不胜感激为找到解决方案提供的一些帮助。

郑重声明,在删除 Azure UI 中的集合后,给出的三个示例中的每一个实际上都会在 Spring 启动时为我创建一个集合。在设置中,分区键显示为“/storeNumber”,这是我没有在 Azure UI 中手动设置的正确分区键。这让我不知所措,为什么编译器抱怨我没有提供分区键,即使 spring boot 直接负责使用我在中看到的(正确的)分区键生成集合蔚蓝 UI.

我正在使用:

        <dependency>
            <groupId>com.microsoft.azure</groupId>
            <artifactId>azure-documentdb</artifactId>
            <version>LATEST</version> 
        </dependency>
        <dependency>
            <groupId>com.microsoft.azure</groupId>
            <artifactId>spring-data-cosmosdb</artifactId>
            <version>2.1.1</version>
        </dependency> <!-- mainly needed for @Id -->

在我的 POM 中。

*** 非常感谢有人指导我在我的问题已经解决后应该做什么。如果将问题标记为重复或完全删除问题是合适的,我会很乐意这样做,但我确实觉得这可能对其他人有用。同时,我将回答我自己的问题,因为给出的答案并没有直接解决它,尽管评论中提供的 link 确实帮助很大。

你必须这样设置,

 PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition();
 Collection<String> paths = new ArrayList<>();
 paths.add(partitionKey);
 partitionKeyDefinition.setPaths(paths);
 collection.setPartitionKey(partitionKeyDefinition);

正如我在问题中所说,在使用 @PartitionKey 注释选择我自己的分区键之前,一切(CRUD/DocumentDbRepository/Custom 方法)都运行良好,而不是让 Microsoft 为我管理它。尽管保存和删除继续正常工作,但 DocumentDbRespository 方法(例如 findById(String id) 等)抛出 UnsupportedOperationException 并抱怨必须提供分区键。这最初令人费解,因为分区密钥是在 Spring 引导中提供的,并在 Spring 引导生成的 cosmos 数据库中注册。解决方案是在存储库中提供映射字段名称的方法签名。例如签名:

public interface TransactionRepository extends DocumentDbRepository<Transaction, String> {
   public List<Transaction> findByTxId(String txId);
}

按预期工作,而此签名:

public Optional<Transaction> findById(String id)

会导致抛出异常。

有关详细信息,请参阅 Sajeetharan 的回答中的评论。此外,Jay Gong 在回答 Nikhil Jain 的问题时提供了很好的解释:.