首页 > 解决方案 > Spring Boot Cosmos DB 实现中的动态查询

问题描述

我正在使用 Azure Cosmos DB for Spring 开发应用程序。

我有一个包含模型类和 ReactiveCosmosRepository 的结构,我用它来进行查询。

我通常在我的存储库类中注释我的查询:

@Repository
public interface ArchivedDocumentRepository extends ReactiveCosmosRepository<ArchivedDocument, String> {

@Query("SELECT * FROM c)
Flux<ArchivedDocument> findAllArchivedDocuments();
    
@Query("SELECT * FROM c where c.document_id = @documentId")
Mono<ArchivedDocument> findArchivedDocument(@Param("documentId") String documentId);
    
}

但是现在我需要使用一些逻辑来创建 SQL,并且不能像这样注释它。我怎样才能做到这一点?

我还直接使用了 Azure Cosmos SDK,您可以这样做:

client = new CosmosClientBuilder().endpoint("SOMEURL")
        .key("SOMEKEY")
        .preferredRegions(Collections.singletonList("SOMELOCATION"))
        .consistencyLevel(ConsistencyLevel.EVENTUAL).buildClient();

database = client.getDatabase("DBNAME");
String containerName = "CONTAINERNAME";
CosmosContainer container = database.getContainer(containerName);

String sql = "SELECT * FROM c";

CosmosPagedIterable<DocumentMetadata> filteredDocumentMetadata = container.queryItems(sql, new CosmosQueryRequestOptions(), DocumentMetadata.class);

...
}

如果我在我的服务中将我现有的存储库代码与类似的代码结合起来,我可以检索我喜欢的数据并构建我喜欢的查询,但是当我已经有一个连接时,实例化“客户端”对象似乎有点不必要?

有什么建议吗?如何将 SDK 直接与 Spring 层结合起来,以便能够基于逻辑创建查询?

标签: azurespring-bootspring-dataazure-cosmosdbazure-cosmosdb-sqlapi

解决方案


我认为你走在正确的道路上。您可能需要在较低级别上使用CosmosAsyncClient

如果您使用的是配置,extends AbstractCosmosConfiguration那么您甚至不需要创建CosmosAsyncClient它,因为它在 AbstractCosmosConfiguration 类中定义。

自定义存储库

package com.vob.reactive.webflux.service;

import com.azure.cosmos.CosmosAsyncClient;
import com.azure.cosmos.models.SqlParameter;
import com.azure.cosmos.models.SqlQuerySpec;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

@Component
@Slf4j
public class CustomRepository {


    private final CosmosAsyncClient cosmosAsyncClient;

    @Autowired
    public CustomRepository(CosmosAsyncClient cosmosAsyncClient) {
        this.cosmosAsyncClient = cosmosAsyncClient;
    }

    public <T> Mono<T> getSomethingFrom(String database, String container, String id, Class<T> classType){
        return this.cosmosAsyncClient
                .getDatabase(database)
                .getContainer(container)
                .queryItems(new SqlQuerySpec("select * from c where c.document_id = @documentId", new SqlParameter("documentId", id)), classType)
                .single();
    }

}

您可能需要通过将 getDatabase 和 getContainer 存储在 Map 中来改进它们,这样您就不需要每次都检查它们是否存在


推荐阅读