我试图通过在我的 Spring Boot 应用程序中使用 join 按地址类型从 cosmosdb 过滤员工数据。 以下是cosmosdb中的员工数据
{
"id": "125",
"name": "Dolly",
"addresses": [
{
"addressType": "home",
"street": "Nagpur"
},
{
"addressType": "office",
"street": "Pune"
}
] }
这是我的pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example.employee.service</groupId>
<artifactId>employee-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>employee-service</name>
<description>employee service</description>
<properties>
<java.version>17</java.version>
<spring-cloud-azure.version>5.11.0</spring-cloud-azure.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter-data-cosmos</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-dependencies</artifactId>
<version>${spring-cloud-azure.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
下面是我的存储库类
@Repository
public interface EmployeeRepository extends CosmosRepository<Employee, String> {
@Query("SELECT * FROM c JOIN a IN c.addresses WHERE a.addressType = @addressType")
List<Employee> findByAddressType(@Param("addressType") String addressType);
}
以下是我的服务等级
@Service
public class EmployeeService {
@Autowired
private EmployeeRepository employeeRepository;
public List<Employee> findByAddressType(String addressType) {
return employeeRepository.findByAddressType(addressType);
}
}
下面是我的employeeController
@RestController
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
@GetMapping("/employees/by-address-type")
public List<Employee> getEmployeesByAddressType(@RequestParam String addressType) {
return employeeService.findByAddressType(addressType);
}
}
当我尝试调用“@GetMapping("/employees/by-address-type?addressType=home")” api 时,出现以下错误
DEBUG 14264 --- [supplier-dataproducts] [nio-8080-exec-2] c.a.c.implementation.SqlQuerySpecLogger : SELECT * FROM c JOIN a IN c.addresses WHERE a.addressType = @addressType
2024-06-14T10:47:29.566+05:30 DEBUG 14264 --- [supplier-dataproducts] [nio-8080-exec-2] c.a.c.implementation.caches.AsyncCache : cache[dbs/sscmxMaster/colls/employees] doesn't exist, computing new value
2024-06-14T10:47:29.567+05:30 DEBUG 14264 --- [supplier-dataproducts] [nio-8080-exec-2] c.a.c.implementation.caches.AsyncLazy : constructor
2024-06-14T10:47:29.570+05:30 DEBUG 14264 --- [supplier-dataproducts] [nio-8080-exec-2] c.a.c.implementation.caches.AsyncLazy : using Function<Mono<TValue>> com.azure.cosmos.implementation.caches.RxCollectionCache$$Lambda$1601/0x000001b4c57d4000@5bf8c934
2024-06-14T10:47:29.781+05:30 DEBUG 14264 --- [supplier-dataproducts] [ctor-http-nio-3] c.a.c.implementation.caches.AsyncCache : set cache[v+xOAMHU++M=]={"id":"employees","indexingPolicy":{"indexingMode":"consistent","automatic":true,"includedPaths":[{"path":"/*"}],"excludedPaths":[{"path":"/\"_etag\"/?"}]},"partitionKey":{"paths":["/null"],"kind":"Hash"},"defaultTtl":-1,"uniqueKeyPolicy":{"uniqueKeys":[]},"conflictResolutionPolicy":{"mode":"LastWriterWins","conflictResolutionPath":"/_ts","conflictResolutionProcedure":""},"backupPolicy":{"type":1},"geospatialConfig":{"type":"Geography"},"_rid":"v+xOAMHU++M=","_ts":1718259475,"_self":"dbs/v+xOAA==/colls/v+xOAMHU++M=/","_etag":"\"00003313-0000-0c00-0000-666a8f130000\"","_docs":"docs/","_sprocs":"sprocs/","_triggers":"triggers/","_udfs":"udfs/","_conflicts":"conflicts/"}
2024-06-14T10:47:29.788+05:30 DEBUG 14264 --- [supplier-dataproducts] [ctor-http-nio-3] c.a.c.implementation.caches.AsyncCache : cache[dbs/sscmxMaster/colls/employees] exists
2024-06-14T10:47:29.791+05:30 DEBUG 14264 --- [supplier-dataproducts] [ctor-http-nio-3] c.a.c.implementation.caches.AsyncCache : Returning cache[dbs/sscmxMaster/colls/employees] as it is different from obsoleteValue
2024-06-14T10:47:30.600+05:30 DEBUG 14264 --- [supplier-dataproducts] [ctor-http-nio-3] c.a.c.i.WebExceptionRetryPolicy : WebExceptionRetryPolicy() No retrying on un-retryable exceptions on endpoint https://sscmx-dev-db-account-northeurope.documents.azure.com:443/, operationType = QueryPlan, resourceType = Document, count = 0, isAddressRefresh = false
2024-06-14T10:47:30.603+05:30 DEBUG 14264 --- [supplier-dataproducts] [ctor-http-nio-3] c.a.c.implementation.ClientRetryPolicy : retry count 1, isReadRequest true, canUseMultipleWriteLocations false, due to failure:
com.azure.cosmos.CosmosException: {"innerErrorMessage":"{\"code\":\"BadRequest\",\"message\":\"One of the input values is invalid.\\r\\nActivityId: 34feb19e-8055-4bf9-8880-dd668d86c6ec, Windows/10.0.20348 cosmos-netstandard-sdk/3.18.0\"}, StatusCode: BadRequest","cosmosDiagnostics":{"userAgent":"azsdk-java-cosmos/4.57.0 Windows11/10.0 JRE/17.0.10 az-sd-cos/5.11.0","activityId":"34feb19e-8055-4bf9-8880-dd668d86c6ec","requestLatencyInMs":814,"requestStartTimeUTC":"2024-06-14T05:17:29.785424500Z","requestEndTimeUTC":"2024-06-14T05:17:30.599804400Z","responseStatisticsList":[],"supplementalResponseStatisticsList":[],"addressResolutionStatistics":{},"regionsContacted":["north europe"],"retryContext":{"statusAndSubStatusCodes":null,"retryCount":0,"retryLatency":0},"metadataDiagnosticsContext":{"metadataDiagnosticList":null},"serializationDiagnosticsContext":{"serializationDiagnosticsList":null},"gatewayStatisticsList":[{"sessionToken":null,"operationType":"QueryPlan","resourceType":"Document","statusCode":400,"subStatusCode":0,"requestCharge":0.0,"requestTimeline":[{"eventName":"connectionCreated","startTimeUTC":"2024-06-14T05:17:29.791924500Z","durationInMilliSecs":510.9615},{"eventName":"connectionConfigured","startTimeUTC":"2024-06-14T05:17:30.302886Z","durationInMilliSecs":0.0},{"eventName":"requestSent","startTimeUTC":"2024-06-14T05:17:30.302886Z","durationInMilliSecs":1.9967},{"eventName":"transitTime","startTimeUTC":"2024-06-14T05:17:30.304882700Z","durationInMilliSecs":283.7429},{"eventName":"received","startTimeUTC":"2024-06-14T05:17:30.588625600Z","durationInMilliSecs":0.0}],"partitionKeyRangeId":null,"responsePayloadSizeInBytes":0,"exceptionMessage":"{\"code\":\"BadRequest\",\"message\":\"One of the input values is invalid.\\r\\nActivityId: 34feb19e-8055-4bf9-8880-dd668d86c6ec, Windows/10.0.20348 cosmos-netstandard-sdk/3.18.0\"}, StatusCode: BadRequest","exceptionResponseHeaders":"{Server=Compute, x-ms-gatewayversion=2.0.0, Content-Length=215, Date=Fri, 14 Jun 2024 05:17:30 GMT, x-ms-activity-id=34feb19e-8055-4bf9-8880-dd668d86c6ec, Content-Type=application/json, x-ms-substatus=0}"}],"samplingRateSnapshot":1.0,"systemInformation":{"usedMemory":"60247 KB","availableMemory":"4031657 KB","systemCpuLoad":"(2024-06-14T05:17:13.744198800Z 5.4%), (2024-06-14T05:17:18.739241700Z 5.2%), (2024-06-14T05:17:23.737563400Z 4.1%), (2024-06-14T05:17:28.746632200Z 5.9%)","availableProcessors":8},"clientCfgs":{"id":1,"machineId":"uuid:26f55ade-8d88-4c44-8b80-ed33cf42a003","connectionMode":"DIRECT","numberOfClients":1,"excrgns":"[]","clientEndpoints":{"https://sscmx-dev-db-account.documents.azure.com:443/":1},"connCfg":{"rntbd":"(cto:PT5S, nrto:PT5S, icto:PT0S, ieto:PT1H, mcpe:130, mrpc:30, cer:true)","gw":"(cps:1000, nrto:PT1M, icto:PT1M, p:false)","other":"(ed: true, cs: false, rv: true)"},"consistencyCfg":"(consistency: null, mm: true, prgns: [])","proactiveInitCfg":"","e2ePolicyCfg":"","sessionRetryCfg":""}}}
at com.azure.cosmos.BridgeInternal.createCosmosException(BridgeInternal.java:478) ~[azure-cosmos-4.57.0.jar:4.57.0]
at com.azure.cosmos.implementation.RxGatewayStoreModel.validateOrThrow(RxGatewayStoreModel.java:504) ~[azure-cosmos-4.57.0.jar:4.57.0]
at com.azure.cosmos.implementation.RxGatewayStoreModel.lambda$toDocumentServiceResponse$1(RxGatewayStoreModel.java:365) ~[azure-cosmos-4.57.0.jar:4.57.0]
at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:106) ~[reactor-core-3.6.6.jar:3.6.6]
at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:74) ~[reactor-core-3.6.6.jar:3.6.6]
at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:200) ~[reactor-core-3.6.6.jar:3.6.6]
at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:122) ~[reactor-core-3.6.6.jar:3.6.6]
我试过了
SELECT *
FROM c
JOIN a IN c.addresses
WHERE a.addressType = 'home'
在 cosmosdb 数据探索中,它按预期工作,但如果我在 Spring Boot 中使用相同的查询,它就不起作用。
我也尝试过不使用@Query
@Repository
public interface EmployeeRepository extends CosmosRepository<Employee, String> {
List<Employee> findByAddressesAddressType(String addressType);
}
我收到 200 个响应,但结果是空白数组 []
发生错误的原因是分区键不匹配,如果分区键在 Azure Cosmos DB 中为
id
但在代码中用作 Id
,则重命名为 id
或添加属性。确保 id
的数据类型为 string
。尝试使用以下成功执行的代码从 Azure Cosmos DB 容器检索具有 addressType: home
的数据,如下面的输出所示。
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>cosmosdb-query</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<!-- Spring Boot Web Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Azure Cosmos DB SDK -->
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-cosmos</artifactId>
<version>4.20.0</version>
</dependency>
<!-- Jackson Databind for JSON processing -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.3</version>
</dependency>
<!-- Spring Boot Starter Test (for testing purposes) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Config.java:
@Configuration
public class CosmosConfig {
private static final String ENDPOINT = "*****";
private static final String KEY = "*****";
private static final String DATABASE_NAME = "firstDb";
private static final String CONTAINER_NAME = "firstCont";
@Bean
public CosmosClient cosmosClient() {
return new CosmosClientBuilder()
.endpoint(ENDPOINT)
.key(KEY)
.preferredRegions(List.of("West US"))
.consistencyLevel(ConsistencyLevel.EVENTUAL)
.buildClient();
}
@Bean
public CosmosDatabase cosmosDatabase(CosmosClient cosmosClient) {
return cosmosClient.getDatabase(DATABASE_NAME);
}
@Bean
public CosmosContainer cosmosContainer(CosmosDatabase cosmosDatabase) {
return cosmosDatabase.getContainer(CONTAINER_NAME);
}
}
Service.java:
@Service
public class CosmosDbService {
@Autowired
private CosmosContainer cosmosContainer;
public void executeQuery() {
String query = "SELECT c.id, c.name, a.addressType, a.street " +
"FROM c " +
"JOIN a IN c.addresses " +
"WHERE a.addressType = 'home'";
CosmosPagedIterable<ObjectNode> items = cosmosContainer.queryItems(query, new CosmosQueryRequestOptions(), ObjectNode.class);
for (ObjectNode item : items) {
System.out.println(item.toString());
}
}
}
输出:
{"id":"125","name":"Dolly","addressType":"home","street":"Nagpur"}