如何在 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 的问题时提供了很好的解释:.
答案似乎很明显,但我已经尝试了多种注释和配置的组合,但无法找到一种在所有情况下都适用的方法(例如执行 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 的问题时提供了很好的解释: