Udostępnij za pośrednictwem


Migrowanie z bazy danych CouchBase do usługi Azure Cosmos DB for NoSQL

DOTYCZY: NoSQL

Azure Cosmos DB to skalowalna, globalnie rozproszona, w pełni zarządzana baza danych. Zapewnia gwarantowany dostęp do danych z małym opóźnieniem. Aby dowiedzieć się więcej na temat usługi Azure Cosmos DB, zobacz artykuł z omówieniem. Ten artykuł zawiera instrukcje dotyczące migrowania aplikacji Java połączonych z bazą danych Couchbase do konta interfejsu API dla noSQL w usłudze Azure Cosmos DB.

Różnice w nomenklaturze

Poniżej przedstawiono kluczowe funkcje, które działają inaczej w usłudze Azure Cosmos DB w porównaniu z bazą danych Couchbase:

Couchbase Azure Cosmos DB
Serwer Couchbase Klient
Wiadro baza danych
Wiadro Kontener/kolekcja
Dokument JSON Element/dokument

Podstawowe różnice

  • Usługa Azure Cosmos DB ma pole "ID" w dokumencie, natomiast couchbase ma identyfikator jako część zasobnika. Pole "ID" jest unikatowe w obrębie partycji.

  • Usługa Azure Cosmos DB skaluje się przy użyciu techniki partycjonowania lub fragmentowania. Oznacza to, że dzieli dane na wiele fragmentów/partycji. Te partycje/fragmenty są tworzone na podstawie podanej właściwości klucza partycji. Możesz również wybrać klucz partycji, aby zoptymalizować operacje odczytu, a także operacje zapisu lub zoptymalizowane pod kątem odczytu/zapisu. Aby dowiedzieć się więcej, zobacz artykuł dotyczący partycjonowania .

  • W usłudze Azure Cosmos DB nie jest wymagane, aby hierarchia najwyższego poziomu oznaczała kolekcję, ponieważ nazwa kolekcji już istnieje. Ta funkcja sprawia, że struktura JSON jest prostsza. Poniżej przedstawiono przykład pokazujący różnice w modelu danych między bazą couchbase i usługą Azure Cosmos DB:

    Couchbase: identyfikator dokumentu = "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: zapoznaj się z "identyfikatorem" w dokumencie, jak pokazano poniżej

    {
      "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"
          }
        ]
      }
    

Obsługa zestawu JAVA SDK

Usługa Azure Cosmos DB ma następujące zestawy SDK (software development kit) do obsługi różnych struktur Języka Java:

  • Asynchroniczny zestaw SDK
  • Spring Boot SDK

W poniższych sekcjach opisano, kiedy należy używać każdego z tych zestawów SDK. Rozważmy przykład, w którym mamy trzy typy obciążeń:

Couchbase jako repozytorium dokumentów i zapytania niestandardowe oparte na danych spring

Jeśli migrowanie obciążenia jest oparte na zestawie SDK platformy Spring Boot, możesz wykonać następujące czynności:

  1. Dodaj element nadrzędny do pliku POM.xml:

    <parent>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-parent</artifactId>
       <version>2.1.5.RELEASE</version>
       <relativePath/>
    </parent>
    
  2. Dodaj właściwości do pliku POM.xml:

    <azure.version>2.1.6</azure.version>
    
  3. Dodaj zależności do pliku POM.xml:

    <dependency>
        <groupId>com.microsoft.azure</groupId>
        <artifactId>azure-cosmosdb-spring-boot-starter</artifactId>
        <version>2.1.6</version>
    </dependency>
    
  4. Dodaj właściwości aplikacji w obszarze zasobów i określ następujące informacje. Pamiętaj, aby zastąpić parametry adresu URL, klucza i nazwy bazy danych:

       azure.cosmosdb.uri=<your-cosmosDB-URL>
       azure.cosmosdb.key=<your-cosmosDB-key>
       azure.cosmosdb.database=<your-cosmosDB-dbName>
    
  5. Zdefiniuj nazwę kolekcji w modelu. Możesz również określić dalsze adnotacje. Na przykład identyfikator, klucz partycji, aby oznaczyć je jawnie:

    @Document(collection = "mycollection")
        public class User {
            @id
            private String id;
            private String firstName;
            @PartitionKey
            private String lastName;
        }
    

Poniżej przedstawiono fragmenty kodu dla operacji CRUD:

Operacje wstawiania i aktualizowania

Gdzie _repo jest obiektem repozytorium, a dokument jest obiektem klasy POJO. Możesz użyć .save polecenia , aby wstawić lub upsert (jeśli dokument z określonym identyfikatorem został znaleziony). Poniższy fragment kodu pokazuje, jak wstawić lub zaktualizować obiekt dokumentu:

_repo.save(doc);

Operacja usuwania

Rozważmy następujący fragment kodu, w którym obiekt dokumentu będzie miał obowiązkowy identyfikator i klucz partycji, aby zlokalizować i usunąć obiekt:

_repo.delete(doc);

Operacja odczytu

Dokument można odczytać z kluczem partycji lub bez jego określania. Jeśli nie określisz klucza partycji, będzie on traktowany jako zapytanie obejmujące wiele partycji. Rozważmy następujące przykłady kodu, najpierw wykonasz operację przy użyciu pola identyfikatora i klucza partycji. W drugim przykładzie użyto zwykłego pola i bez określania pola klucza partycji.

  • _repo.findByIdAndName(objDoc.getId(),objDoc.getName());
  • _repo.findAllByStatus(objDoc.getStatus());

Teraz możesz używać aplikacji z usługą Azure Cosmos DB. Kompletny przykładowy kod dla przykładu opisanego w tym dokumentacji jest dostępny w repozytorium GitHub CouchbaseToCosmosDB-SpringCosmos .

Couchbase jako repozytorium dokumentów i używanie zapytań N1QL

Zapytania N1QL to sposób definiowania zapytań w bazie couchbase.

Zapytanie N1QL Zapytanie usługi Azure Cosmos DB
SELECT META(TravelDocument).id AS id, TravelDocument.* FROM TravelDocument WHERE _type = "com.xx.xxx.xxx.xxxx " and country = 'India' and ANY m in Visas SATISFIES m.type == 'Multi-Entry' and m.Country IN ['India', Bhutan'] ORDER BY 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" and c.country = 'India' and m.type = 'Multi-Entry' and m.Country IN ('India', 'Bhutan') ORDER BY c.Validity DESC OFFSET 0 LIMIT 25

W zapytaniach N1QL można zauważyć następujące zmiany:

  • Nie musisz używać słowa kluczowego META ani odwoływać się do dokumentu pierwszego poziomu. Zamiast tego możesz utworzyć własne odwołanie do kontenera. W tym przykładzie uznaliśmy go za "c" (może to być wszystko). To odwołanie jest używane jako prefiks dla wszystkich pól pierwszego poziomu. Przykład, c.id, kraj c.itp.

  • Zamiast "ANY" można teraz wykonać sprzężenie w dokumentach podrzędnych i odwoływać się do niego za pomocą dedykowanego aliasu, takiego jak "m". Po utworzeniu aliasu dla dokumentu podrzędnego należy użyć aliasu. Na przykład m.Country.

  • Sekwencja przesunięcia różni się w zapytaniu usługi Azure Cosmos DB, najpierw musisz określić PRZESUNIĘCIE, a następnie LIMIT. Zaleca się, aby nie używać zestawu Spring Data SDK, jeśli używasz maksymalnych zapytań zdefiniowanych przez użytkownika, ponieważ może mieć niepotrzebne obciążenie po stronie klienta podczas przekazywania zapytania do usługi Azure Cosmos DB. Zamiast tego mamy bezpośredni zestaw JAVA SDK asynchroniczny, który w tym przypadku może być używany znacznie wydajnie.

Operacja odczytu

Użyj zestawu Async Java SDK, wykonując następujące czynności:

  1. Skonfiguruj następującą zależność do pliku 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>
    
  2. Utwórz obiekt połączenia dla usługi Azure Cosmos DB przy użyciu ConnectionBuilder metody, jak pokazano w poniższym przykładzie. Upewnij się, że ta deklaracja została umieszczona w fasoli, tak aby następujący kod został wykonany tylko raz:

    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);
    
  3. Aby wykonać zapytanie, należy uruchomić następujący fragment kodu:

    Flux<FeedResponse<CosmosItemProperties>> objFlux= container.queryItems(query, fo);
    

Teraz za pomocą powyższej metody można przekazać wiele zapytań i wykonać bez żadnych problemów. Jeśli wymagane jest wykonanie jednego dużego zapytania, które można podzielić na wiele zapytań, spróbuj wykonać poniższy fragment kodu zamiast poprzedniego:

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();
}

Za pomocą poprzedniego kodu można uruchamiać zapytania równolegle i zwiększać liczbę rozproszonych wykonań w celu optymalizacji. Ponadto można również uruchomić operacje wstawiania i aktualizacji:

Operacja wstawiania

Aby wstawić dokument, uruchom następujący kod:

Mono<CosmosItemResponse> objMono= container.createItem(doc,ro);

Następnie subskrybuj usługę Mono jako:

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();

Operacja upsert

Operacja upsert wymaga określenia dokumentu, który ma zostać zaktualizowany. Aby pobrać pełny dokument, możesz użyć fragmentu kodu wymienionego w operacji odczytu nagłówka, a następnie zmodyfikować wymagane pola. Poniższy fragment kodu upertuje dokument:

Mono<CosmosItemResponse> obs= container.upsertItem(doc, ro);

Następnie zasubskrybuj plik mono. Zapoznaj się z fragmentem kodu subskrypcji mono w operacji wstawiania.

Operacja usuwania

Wykonanie operacji usuwania następującego fragmentu kodu:

CosmosItem objItem= container.getItem(doc.Id, doc.Tenant);
Mono<CosmosItemResponse> objMono = objItem.delete(ro);

Następnie zasubskrybuj mono fragment kodu subskrypcji w operacji wstawiania. Kompletny przykładowy kod jest dostępny w repozytorium GitHub CouchbaseToCosmosDB-AsyncInSpring .

Couchbase jako para klucz/wartość

Jest to prosty typ obciążenia, w którym można wykonywać wyszukiwania zamiast zapytań. Wykonaj następujące kroki dla par klucz/wartość:

  1. Rozważ użycie wartości "/ID" jako klucza podstawowego, co gwarantuje, że możesz wykonać operację wyszukiwania bezpośrednio w określonej partycji. Utwórz kolekcję i określ wartość "/ID" jako klucz partycji.

  2. Wyłącz indeksowanie całkowicie. Ponieważ wykonasz operacje wyszukiwania, nie ma sensu przenoszenia obciążenia indeksowania. Aby wyłączyć indeksowanie, zaloguj się do witryny Azure Portal, przejdź do konta usługi Azure Cosmos DB. Otwórz Eksploratora danych, wybierz bazę danych i kontener. Otwórz kartę Skalowanie i ustawienia i wybierz zasady indeksowania. Obecnie zasady indeksowania wyglądają następująco:

    {
     "indexingMode": "consistent",
     "automatic": true,
     "includedPaths": [
         {
             "path": "/*"
         }
     ],
     "excludedPaths": [
         {
             "path": "/\"_etag\"/?"
         }
     ]
     }
    

    Zastąp powyższe zasady indeksowania następującymi zasadami:

    {
     "indexingMode": "none",
     "automatic": false,
     "includedPaths": [],
     "excludedPaths": []
     }
    
  3. Użyj poniższego fragmentu kodu, aby utworzyć obiekt połączenia. Obiekt połączenia (do umieszczenia w @Bean obiekcie lub ustawić go jako statyczny):

    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);
    

Teraz możesz wykonać operacje CRUD w następujący sposób:

Operacja odczytu

Aby odczytać element, użyj następującego fragmentu kodu:

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();

Operacja wstawiania

Aby wstawić element, możesz wykonać następujący kod:

Mono<CosmosItemResponse> objMono= container.createItem(doc,ro);

Następnie subskrybuj plik mono jako:

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();

Operacja upsert

Aby zaktualizować wartość elementu, zapoznaj się z poniższym fragmentem kodu:

Mono<CosmosItemResponse> obs= container.upsertItem(doc, ro);

Następnie zasubskrybuj mono fragment kodu subskrypcji w operacji wstawiania.

Operacja usuwania

Użyj następującego fragmentu kodu, aby wykonać operację usuwania:

CosmosItem objItem= container.getItem(id, id);
Mono<CosmosItemResponse> objMono = objItem.delete(ro);

Następnie zasubskrybuj mono fragment kodu subskrypcji w operacji wstawiania. Kompletny przykładowy kod jest dostępny w repozytorium GitHub CouchbaseToCosmosDB-AsyncKeyValue .

Migracja danych

Migrowanie danych za pomocą usługi Azure Data Factory . Jest to najbardziej zalecana metoda migracji danych. Aby uzyskać szczegółowe instrukcje, zobacz artykuł Dotyczący źródła jako bazy danych Couchbase i ujścia jako azure Cosmos DB for NoSQL. Aby uzyskać szczegółowe instrukcje, zobacz artykuł Dotyczący łącznika usługi Azure Cosmos DB Data Factory.

Następne kroki