Migrar do CouchBase para o Azure Cosmos DB para NoSQL
APLICA-SE A: NoSQL
O Azure Cosmos DB é um banco de dados escalável, distribuído globalmente e totalmente gerenciado. Ele fornece acesso garantido de baixa latência aos seus dados. Para saber mais sobre o Azure Cosmos DB, consulte o artigo de visão geral . Este artigo fornece instruções para migrar aplicativos Java conectados ao Couchbase para uma API para conta NoSQL no Azure Cosmos DB.
Diferenças de nomenclatura
A seguir estão os principais recursos que funcionam de forma diferente no Azure Cosmos DB quando comparado ao Couchbase:
Couchbase | Azure Cosmos DB |
---|---|
Servidor Couchbase | Account |
Balde | Base de Dados |
Balde | Contentor/Recolha |
Documento JSON | Item / Documento |
Diferenças principais
O Azure Cosmos DB tem um campo "ID" dentro do documento, enquanto o Couchbase tem a ID como parte do bucket. O campo "ID" é exclusivo em toda a partição.
O Azure Cosmos DB é dimensionado usando a técnica de particionamento ou fragmentação. O que significa que divide os dados em vários fragmentos / partições. Essas partições/fragmentos são criados com base na propriedade de chave de partição que você fornece. Você pode selecionar a chave de partição para otimizar as operações de leitura, bem como gravação ou leitura / gravação otimizada também. Para saber mais, consulte o artigo de particionamento .
No Azure Cosmos DB, não é necessário que a hierarquia de nível superior denote a coleção porque o nome da coleção já existe. Esse recurso torna a estrutura JSON mais simples. A seguir está um exemplo que mostra as diferenças no modelo de dados entre o Couchbase e o Azure Cosmos DB:
Couchbase: ID do documento = "99FF4444"
{ "TravelDocument": { "Country":"India", "Validity" : "2022-09-01", "Person": { "Name": "Manish", "Address": "AB Road, City-z" }, "Visas": [ { "Country":"India", "Type":"Multi-Entry", "Validity":"2022-09-01" }, { "Country":"US", "Type":"Single-Entry", "Validity":"2022-08-01" } ] } }
Azure Cosmos DB: Consulte "ID" no documento, conforme mostrado abaixo
{ "id" : "99FF4444", "Country":"India", "Validity" : "2022-09-01", "Person": { "Name": "Manish", "Address": "AB Road, City-z" }, "Visas": [ { "Country":"India", "Type":"Multi-Entry", "Validity":"2022-09-01" }, { "Country":"US", "Type":"Single-Entry", "Validity":"2022-08-01" } ] }
Suporte a Java SDK
O Azure Cosmos DB tem os seguintes kits de desenvolvimento de software (SDKs) para dar suporte a diferentes estruturas Java:
- SDK assíncrono
- SDK de inicialização do Spring
As seções a seguir descrevem quando usar cada um desses SDKs. Considere um exemplo em que temos três tipos de cargas de trabalho:
Couchbase como repositório de documentos & consultas personalizadas baseadas em dados spring
Se a carga de trabalho que você está migrando for baseada no Spring Boot Based SDK, você poderá usar as seguintes etapas:
Adicione pai ao arquivo POM.xml:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.5.RELEASE</version> <relativePath/> </parent>
Adicione propriedades ao arquivo POM.xml:
<azure.version>2.1.6</azure.version>
Adicione dependências ao arquivo POM.xml:
<dependency> <groupId>com.microsoft.azure</groupId> <artifactId>azure-cosmosdb-spring-boot-starter</artifactId> <version>2.1.6</version> </dependency>
Adicione as propriedades do aplicativo em recursos e especifique o seguinte. Certifique-se de substituir os parâmetros URL, chave e nome do banco de dados:
azure.cosmosdb.uri=<your-cosmosDB-URL> azure.cosmosdb.key=<your-cosmosDB-key> azure.cosmosdb.database=<your-cosmosDB-dbName>
Defina o nome da coleção no modelo. Você também pode especificar outras anotações. Por exemplo, ID, chave de partição para denotá-los explicitamente:
@Document(collection = "mycollection") public class User { @id private String id; private String firstName; @PartitionKey private String lastName; }
A seguir estão os trechos de código para operações CRUD:
Inserir e atualizar operações
Onde _repo é o objeto do repositório e doc é o objeto da classe POJO. Você pode usar .save
para inserir ou atualizar (se o documento com ID especificado for encontrado). O trecho de código a seguir mostra como inserir ou atualizar um objeto doc:
_repo.save(doc);
Excluir operação
Considere o seguinte trecho de código, onde o objeto doc terá ID e chave de partição obrigatórias para localizar e excluir o objeto:
_repo.delete(doc);
Operação de Leitura
Você pode ler o documento com ou sem especificar a chave de partição. Se você não especificar a chave de partição, ela será tratada como uma consulta entre partições. Considere os seguintes exemplos de código, primeiro um executará a operação usando ID e campo de chave de partição. O segundo exemplo usa um campo regular & sem especificar o campo de chave de partição.
_repo.findByIdAndName(objDoc.getId(),objDoc.getName());
_repo.findAllByStatus(objDoc.getStatus());
É isso, agora você pode usar seu aplicativo com o Azure Cosmos DB. Exemplo de código completo para o exemplo descrito neste documento está disponível no repositório GitHub CouchbaseToCosmosDB-SpringCosmos .
Couchbase como um repositório de documentos & usando consultas N1QL
Consultas N1QL é a maneira de definir consultas no Couchbase.
Consulta N1QL | Consulta do Azure Cosmos DB |
---|---|
SELECT META(TravelDocument ).id AS id, TravelDocument .* FROM TravelDocument WHERE _type = "com.xx.xx.xx.xxx.xxx.xxxx " e country = 'Índia' e ANY m em Vistos SATISFAZ m.type == 'Multi-Entry' e m.Country IN ['India', Butão'] ORDEM POR Validity DESC LIMIT 25 OFFSET 0 |
SELECT c.id,c FROM c JOIN m in c.country='India' WHERE c._type = " com.xx.xx.xx.xxx.xxx.xxxx" e c.country = 'India' and m.type = 'Multi-Entry' e m.Country IN ('India', 'Butão') ORDER BY c.Validity DESC OFFSET 0 LIMIT 25 |
Você pode notar as seguintes alterações em suas consultas N1QL:
Você não precisa usar a palavra-chave META ou fazer referência ao documento de primeiro nível. Em vez disso, você pode criar sua própria referência ao contêiner. Neste exemplo, considerámo-lo como "c" (pode ser qualquer coisa). Essa referência é usada como um prefixo para todos os campos de primeiro nível. Fr exemplo, c.id, c.country etc.
Em vez de "ANY" agora você pode fazer uma junção no subdocumento e encaminhá-lo com um alias dedicado, como "m". Depois de criar o alias para um subdocumento, você precisa usar o alias. Por exemplo, m.Country.
A sequência de OFFSET é diferente na consulta do Azure Cosmos DB, primeiro você precisa especificar OFFSET e depois LIMIT. É recomendável não usar o Spring Data SDK se você estiver usando o máximo de consultas personalizadas definidas, pois isso pode ter sobrecarga desnecessária no lado do cliente ao passar a consulta para o Azure Cosmos DB. Em vez disso, temos um SDK Java assíncrono direto, que pode ser utilizado de forma muito eficiente neste caso.
Operação de leitura
Use o Async Java SDK com as seguintes etapas:
Configure a seguinte dependência no arquivo POM.xml:
<!-- https://mvnrepository.com/artifact/com.microsoft.azure/azure-cosmosdb --> <dependency> <groupId>com.microsoft.azure</groupId> <artifactId>azure-cosmos</artifactId> <version>3.0.0</version> </dependency>
Crie um objeto de conexão para o Azure Cosmos DB usando o
ConnectionBuilder
método mostrado no exemplo a seguir. Certifique-se de colocar essa declaração no bean de modo que o código a seguir seja executado apenas uma vez:ConnectionPolicy cp=new ConnectionPolicy(); cp.connectionMode(ConnectionMode.DIRECT); if(client==null) client= CosmosClient.builder() .endpoint(Host)//(Host, PrimaryKey, dbName, collName).Builder() .connectionPolicy(cp) .key(PrimaryKey) .consistencyLevel(ConsistencyLevel.EVENTUAL) .build(); container = client.getDatabase(_dbName).getContainer(_collName);
Para executar a consulta, você precisa executar o seguinte trecho de código:
Flux<FeedResponse<CosmosItemProperties>> objFlux= container.queryItems(query, fo);
Agora, com a ajuda do método acima, você pode passar várias consultas e executar sem qualquer aborrecimento. Caso você tenha o requisito de executar uma consulta grande, que pode ser dividida em várias consultas, tente o seguinte trecho de código em vez do anterior:
for(SqlQuerySpec query:queries)
{
objFlux= container.queryItems(query, fo);
objFlux .publishOn(Schedulers.elastic())
.subscribe(feedResponse->
{
if(feedResponse.results().size()>0)
{
_docs.addAll(feedResponse.results());
}
},
Throwable::printStackTrace,latch::countDown);
lstFlux.add(objFlux);
}
Flux.merge(lstFlux);
latch.await();
}
Com o código anterior, você pode executar consultas em paralelo e aumentar as execuções distribuídas para otimizar. Além disso, você também pode executar as operações de inserção e atualização:
Inserir operação
Para inserir o documento, execute o seguinte código:
Mono<CosmosItemResponse> objMono= container.createItem(doc,ro);
Então assine o Mono como:
CountDownLatch latch=new CountDownLatch(1);
objMono .subscribeOn(Schedulers.elastic())
.subscribe(resourceResponse->
{
if(resourceResponse.statusCode()!=successStatus)
{
throw new RuntimeException(resourceResponse.toString());
}
},
Throwable::printStackTrace,latch::countDown);
latch.await();
Operação Upsert
A operação Upsert requer que você especifique o documento que precisa ser atualizado. Para obter o documento completo, você pode usar o trecho mencionado na operação de leitura do título e, em seguida, modificar o(s) campo(s) obrigatório(s). O seguinte trecho de código atualiza o documento:
Mono<CosmosItemResponse> obs= container.upsertItem(doc, ro);
Então assine o mono. Consulte o trecho de assinatura mono na operação de inserção.
Excluir operação
O trecho a seguir fará a operação de exclusão:
CosmosItem objItem= container.getItem(doc.Id, doc.Tenant);
Mono<CosmosItemResponse> objMono = objItem.delete(ro);
Em seguida, assine o mono, consulte o trecho de assinatura mono na operação de inserção. O exemplo de código completo está disponível no repositório CouchbaseToCosmosDB-AsyncInSpring GitHub.
Couchbase como um par chave/valor
Este é um tipo simples de carga de trabalho na qual você pode realizar pesquisas em vez de consultas. Use as seguintes etapas para pares chave/valor:
Considere ter "/ID" como chave primária, o que garantirá que você possa executar a operação de pesquisa diretamente na partição específica. Crie uma coleção e especifique "/ID" como chave de partição.
Desligue completamente a indexação. Como você executará operações de pesquisa, não há nenhum ponto de carregar a sobrecarga de indexação. Para desativar a indexação, entre no portal do Azure, vá para Conta do Azure Cosmos DB. Abra o Data Explorer, selecione seu Banco de Dados e o Contêiner. Abra a guia Dimensionar & Configurações e selecione a Política de indexação. Atualmente, a política de indexação tem a seguinte aparência:
{ "indexingMode": "consistent", "automatic": true, "includedPaths": [ { "path": "/*" } ], "excludedPaths": [ { "path": "/\"_etag\"/?" } ] }
Substitua a política de indexação acima pela seguinte política:
{ "indexingMode": "none", "automatic": false, "includedPaths": [], "excludedPaths": [] }
Use o trecho de código a seguir para criar o objeto de conexão. Objeto de conexão (a ser colocado @Bean ou torná-lo estático):
ConnectionPolicy cp=new ConnectionPolicy(); cp.connectionMode(ConnectionMode.DIRECT); if(client==null) client= CosmosClient.builder() .endpoint(Host)//(Host, PrimaryKey, dbName, collName).Builder() .connectionPolicy(cp) .key(PrimaryKey) .consistencyLevel(ConsistencyLevel.EVENTUAL) .build(); container = client.getDatabase(_dbName).getContainer(_collName);
Agora você pode executar as operações CRUD da seguinte maneira:
Operação de leitura
Para ler o item, use o seguinte trecho:
CosmosItemRequestOptions ro=new CosmosItemRequestOptions();
ro.partitionKey(new PartitionKey(documentId));
CountDownLatch latch=new CountDownLatch(1);
var objCosmosItem= container.getItem(documentId, documentId);
Mono<CosmosItemResponse> objMono = objCosmosItem.read(ro);
objMono .subscribeOn(Schedulers.elastic())
.subscribe(resourceResponse->
{
if(resourceResponse.item()!=null)
{
doc= resourceResponse.properties().toObject(UserModel.class);
}
},
Throwable::printStackTrace,latch::countDown);
latch.await();
Inserir operação
Para inserir um item, você pode executar o seguinte código:
Mono<CosmosItemResponse> objMono= container.createItem(doc,ro);
Então assine o mono como:
CountDownLatch latch=new CountDownLatch(1);
objMono.subscribeOn(Schedulers.elastic())
.subscribe(resourceResponse->
{
if(resourceResponse.statusCode()!=successStatus)
{
throw new RuntimeException(resourceResponse.toString());
}
},
Throwable::printStackTrace,latch::countDown);
latch.await();
Operação Upsert
Para atualizar o valor de um item, consulte o trecho de código abaixo:
Mono<CosmosItemResponse> obs= container.upsertItem(doc, ro);
Em seguida, assine o mono, consulte o trecho de assinatura mono na operação de inserção.
Excluir operação
Use o seguinte trecho para executar a operação de exclusão:
CosmosItem objItem= container.getItem(id, id);
Mono<CosmosItemResponse> objMono = objItem.delete(ro);
Em seguida, assine o mono, consulte o trecho de assinatura mono na operação de inserção. O exemplo de código completo está disponível no repositório CouchbaseToCosmosDB-AsyncKeyValue GitHub.
Migração de Dados
Use o Azure Data Factory para migrar dados. Este é o método mais recomendado para migrar os dados. Configure a origem como Couchbase e coletor como Azure Cosmos DB para NoSQL, consulte o artigo do conector do Azure Azure Cosmos DB Data Factory para obter etapas detalhadas.
Passos Seguintes
- Para fazer testes de desempenho, consulte o artigo Testes de desempenho e dimensionamento com o Azure Cosmos DB .
- Para otimizar o código, consulte o artigo Dicas de desempenho para o Azure Cosmos DB .
- Explore Java Async V3 SDK, SDK referência GitHub repo.