Delen via


Uw toepassing migreren van Amazon DynamoDB naar Azure Cosmos DB

VAN TOEPASSING OP: NoSQL

Azure Cosmos DB is een schaalbare, wereldwijd gedistribueerde, volledig beheerde database. Het biedt gegarandeerde toegang tot lage latentie tot uw gegevens. Zie het overzichtsartikel voor meer informatie over Azure Cosmos DB. In dit artikel wordt beschreven hoe u uw .NET-toepassing migreert van DynamoDB naar Azure Cosmos DB met minimale codewijzigingen.

Conceptuele verschillen

Hier volgen de belangrijkste conceptuele verschillen tussen Azure Cosmos DB en DynamoDB:

DynamoDB Azure Cosmos DB
Niet van toepassing Database
Tabel Verzameling
Artikel Document
Kenmerk Veld
Secundaire index Secundaire index
Primaire sleutel : partitiesleutel Partitiesleutel
Primaire sleutel : sorteersleutel Niet vereist
Stream ChangeFeed
Rekeneenheid schrijven Aanvraageenheid (Flexibel, kan worden gebruikt voor lees- of schrijfbewerkingen)
Rekeneenheid lezen Aanvraageenheid (Flexibel, kan worden gebruikt voor lees- of schrijfbewerkingen)
Globale tabellen Niet vereist. U kunt de regio rechtstreeks selecteren tijdens het inrichten van het Azure Cosmos DB-account (u kunt de regio later wijzigen)

Structurele verschillen

Azure Cosmos DB heeft een eenvoudigere JSON-structuur in vergelijking met die van DynamoDB. In het volgende voorbeeld ziet u de verschillen

DynamoDB:

Het volgende JSON-object vertegenwoordigt de gegevensindeling in DynamoDB

{
TableName: "Music",
KeySchema: [
{ 
  AttributeName: "Artist",
  KeyType: "HASH", //Partition key
},
{ 
  AttributeName: "SongTitle",
  KeyType: "RANGE" //Sort key
}
],
AttributeDefinitions: [
{ 
  AttributeName: "Artist",
  AttributeType: "S"
},
{ 
  AttributeName: "SongTitle",
  AttributeType: "S"
}
],
ProvisionedThroughput: {
  ReadCapacityUnits: 1,
  WriteCapacityUnits: 1
 }
}

Azure Cosmos DB:

Het volgende JSON-object vertegenwoordigt de gegevensindeling in Azure Cosmos DB

{
"Artist": "",
"SongTitle": "",
"AlbumTitle": "",
"Year": 9999,
"Price": 0.0,
"Genre": "",
"Tags": ""
}

Uw code migreren

Dit artikel is bedoeld voor het migreren van de code van een toepassing naar Azure Cosmos DB. Dit is het kritieke aspect van databasemigratie. Om de leercurve te verminderen, bevatten de volgende secties een vergelijking van code naast elkaar tussen Amazon DynamoDB en het equivalente codefragment van Azure Cosmos DB.

Kloon de volgende opslagplaats om de broncode te downloaden:

git clone https://github.com/Azure-Samples/DynamoDB-to-CosmosDB

Vereisten

  • .NET Framework 4.7.2
  • Nieuwste Visual Studio met de Azure-ontwikkelworkload. U kunt aan de slag met de gratis Visual Studio Community IDE. Schakel de Azure-ontwikkelworkload in tijdens het instellen van Visual Studio.
  • Toegang tot Azure Cosmos DB for NoSQL-account
  • Lokale installatie van Amazon DynamoDB
  • Java 8
  • Voer de downloadbare versie van Amazon DynamoDB uit op poort 8000 (u kunt de code wijzigen en configureren)

Uw code instellen

Voeg het volgende NuGet-pakket toe aan uw project:

Install-Package Microsoft.Azure.Cosmos

Verbinding maken

DynamoDB:

In Amazon DynamoDB wordt de volgende code gebruikt om verbinding te maken:

    AmazonDynamoDBConfig addbConfig = new AmazonDynamoDBConfig() ;
        addbConfig.ServiceURL = "endpoint";
        try { aws_dynamodbclient = new AmazonDynamoDBClient( addbConfig ); }

Azure Cosmos DB:

Werk uw code bij om Azure Cosmos DB te verbinden met:

client_documentDB = new CosmosClient(
    "<nosql-account-endpoint>",
    tokenCredential
);

De verbinding optimaliseren in Azure Cosmos DB

Met Azure Cosmos DB kunt u de volgende opties gebruiken om uw verbinding te optimaliseren:

  • ConnectionMode : gebruik de modus directe verbinding om verbinding te maken met de gegevensknooppunten in de Azure Cosmos DB-service. Gebruik de gatewaymodus alleen om de logische adressen te initialiseren en in de cache te plaatsen en bij updates te vernieuwen. Zie de connectiviteitsmodi voor meer informatie.

  • ApplicationRegion : deze optie wordt gebruikt om de voorkeursregio voor geo-replicatie in te stellen die wordt gebruikt om te communiceren met Azure Cosmos DB. Zie de wereldwijde distributie voor meer informatie.

  • ConsistencyLevel : deze optie wordt gebruikt om het standaardconsistentieniveau te overschrijven. Zie consistentieniveaus voor meer informatie.

  • BulkExecutionMode : deze optie wordt gebruikt om bulkbewerkingen uit te voeren door de eigenschap AllowBulkExecution in te stellen op true. Zie bulkimport voor meer informatie.

    client_cosmosDB = new CosmosClient(" Your connection string ",new CosmosClientOptions()
    { 
      ConnectionMode=ConnectionMode.Direct,
      ApplicationRegion=Regions.EastUS2,
      ConsistencyLevel=ConsistencyLevel.Session,
      AllowBulkExecution=true  
    });
    

De container maken

DynamoDB:

Als u de gegevens wilt opslaan in Amazon DynamoDB, moet u eerst de tabel maken. In het proces voor het maken van tabellen; u het schema, het sleuteltype en de kenmerken definieert, zoals wordt weergegeven in de volgende code:

// movies_key_schema
public static List<KeySchemaElement> movies_key_schema
  = new List<KeySchemaElement>
{
  new KeySchemaElement
  {
    AttributeName = partition_key_name,
    KeyType = "HASH"
  },
  new KeySchemaElement
  {
    AttributeName = sort_key_name,
    KeyType = "RANGE"
  }
};

// key names for the Movies table
public const string partition_key_name = "year";
public const string sort_key_name      = "title";
  public const int readUnits=1, writeUnits=1; 

    // movie_items_attributes
    public static List<AttributeDefinition> movie_items_attributes
  = new List<AttributeDefinition>
{
  new AttributeDefinition
  {
    AttributeName = partition_key_name,
    AttributeType = "N"
  },
  new AttributeDefinition
  {
    AttributeName = sort_key_name,
    AttributeType = "S"
  }

CreateTableRequest  request;
CreateTableResponse response;

// Build the 'CreateTableRequest' structure for the new table
request = new CreateTableRequest
{
  TableName             = table_name,
  AttributeDefinitions  = table_attributes,
  KeySchema             = table_key_schema,
  // Provisioned-throughput settings are always required,
  // although the local test version of DynamoDB ignores them.
  ProvisionedThroughput = new ProvisionedThroughput( readUnits, writeUnits );
};

Azure Cosmos DB:

In Amazon DynamoDB moet u de lees-rekeneenheden inrichten en rekeneenheden schrijven. Terwijl u in Azure Cosmos DB de doorvoer opgeeft als aanvraageenheden (RU/s), die dynamisch kunnen worden gebruikt voor bewerkingen. De gegevens zijn ingedeeld als database --> container--> item. U kunt de doorvoer opgeven op databaseniveau of op verzamelingsniveau of beide.

Een database maken:

await client_cosmosDB.CreateDatabaseIfNotExistsAsync(movies_table_name);

De container maken:

await cosmosDatabase.CreateContainerIfNotExistsAsync(new ContainerProperties() { PartitionKeyPath = "/" + partitionKey, Id = new_collection_name }, provisionedThroughput);

De gegevens laden

DynamoDB:

De volgende code laat zien hoe u de gegevens in Amazon DynamoDB laadt. De filmsArray bestaat uit een lijst met JSON-documenten, dan moet u het JSON-document herhalen en laden in Amazon DynamoDB:

int n = moviesArray.Count;
for( int i = 0, j = 99; i < n; i++ )
    {
  try
  {
    string itemJson = moviesArray[i].ToString();
    Document doc = Document.FromJson(itemJson);
    Task putItem = moviesTable.PutItemAsync(doc);
    if( i >= j )
    {
      j++;
      Console.Write( "{0,5:#,##0}, ", j );
      if( j % 1000 == 0 )
        Console.Write( "\n " );
      j += 99;
    }
    await putItem;

Azure Cosmos DB:

In Azure Cosmos DB kunt u kiezen voor stream en schrijven met moviesContainer.CreateItemStreamAsync(). In dit voorbeeld wordt de JSON echter gedeserialiseerd in het type MovieModel om de functie type casting te demonstreren. De code is multithreaded, die gebruikmaakt van de gedistribueerde architectuur van Azure Cosmos DB en de laadbewerking versnelt:

List<Task> concurrentTasks = new List<Task>();
for (int i = 0, j = 99; i < n; i++)
{
  try
  {
      MovieModel doc= JsonConvert.DeserializeObject<MovieModel>(moviesArray[i].ToString());
      doc.Id = Guid.NewGuid().ToString();
      concurrentTasks.Add(moviesContainer.CreateItemAsync(doc,new PartitionKey(doc.Year)));
      {
          j++;
          Console.Write("{0,5:#,##0}, ", j);
          if (j % 1000 == 0)
              Console.Write("\n               ");
          j += 99;
      }
      
  }
  catch (Exception ex)
  {
      Console.WriteLine("\n     ERROR: Could not write the movie record #{0:#,##0}, because:\n       {1}",
                          i, ex.Message);
      operationFailed = true;
      break;
  }
}
await Task.WhenAll(concurrentTasks);

Een document maken

DynamoDB:

Het schrijven van een nieuw document in Amazon DynamoDB is niet veilig. In het volgende voorbeeld wordt newItem gebruikt als documenttype:

Task<Document> writeNew = moviesTable.PutItemAsync(newItem, token);
await writeNew;

Azure Cosmos DB:

Azure Cosmos DB biedt u typeveiligheid via het gegevensmodel. We gebruiken het gegevensmodel met de naam MovieModel:

public class MovieModel
{
    [JsonProperty("id")]
    public string Id { get; set; }
    [JsonProperty("title")]
    public string Title{ get; set; }
    [JsonProperty("year")]
    public int Year { get; set; }
    public MovieModel(string title, int year)
    {
        this.Title = title;
        this.Year = year;
    }
    public MovieModel()
    {

    }
    [JsonProperty("info")]
    public   MovieInfo MovieInfo { get; set; }

    internal string PrintInfo()
    {
        if(this.MovieInfo!=null)
        return            string.Format("\nMovie with title:{1}\n Year: {2}, Actors: {3}\n Directors:{4}\n Rating:{5}\n", this.Id, this.Title, this.Year, String.Join(",",this.MovieInfo.Actors), this.MovieInfo, this.MovieInfo.Rating);
        else
            return string.Format("\nMovie with  title:{0}\n Year: {1}\n",  this.Title, this.Year);
    }
}

In Azure Cosmos DB newItem wordt MovieModel:

 MovieModel movieModel = new MovieModel()
            {
                Id = Guid.NewGuid().ToString(),
                Title = "The Big New Movie",
                Year = 2018,
                MovieInfo = new MovieInfo() { Plot = "Nothing happens at all.", Rating = 0 }
            };
    var writeNew= moviesContainer.CreateItemAsync(movieModel, new Microsoft.Azure.Cosmos.PartitionKey(movieModel.Year));
    await writeNew;

Een document lezen

DynamoDB:

Als u in Amazon DynamoDB wilt lezen, moet u primitieven definiëren:

// Create Primitives for the HASH and RANGE portions of the primary key
Primitive hash = new Primitive(year.ToString(), true);
Primitive range = new Primitive(title, false);

  Task<Document> readMovie = moviesTable.GetItemAsync(hash, range, token);
  movie_record = await readMovie;

Azure Cosmos DB:

Met Azure Cosmos DB is de query echter natuurlijk (LINQ):

IQueryable<MovieModel> movieQuery = moviesContainer.GetItemLinqQueryable<MovieModel>(true)
                        .Where(f => f.Year == year && f.Title == title);
// The query is executed synchronously here, but can also be executed asynchronously via the IDocumentQuery<T> interface
    foreach (MovieModel movie in movieQuery)
    {
      movie_record_cosmosdb = movie;
    }

De verzameling documenten in het bovenstaande voorbeeld is:

  • type veilig
  • geef een natuurlijke queryoptie op.

Een item bijwerken

DynamoDB: Het item bijwerken in Amazon DynamoDB:

updateResponse = await client.UpdateItemAsync( updateRequest );

Azure Cosmos DB:

In Azure Cosmos DB wordt de update behandeld als Upsert-bewerking, wat betekent dat het document wordt ingevoegd als het niet bestaat:

await moviesContainer.UpsertItemAsync<MovieModel>(updatedMovieModel);

Een document verwijderen

DynamoDB:

Als u een item in Amazon DynamoDB wilt verwijderen, moet u opnieuw vallen op primitieven:

Primitive hash = new Primitive(year.ToString(), true);
      Primitive range = new Primitive(title, false);
      DeleteItemOperationConfig deleteConfig = new DeleteItemOperationConfig( );
      deleteConfig.ConditionalExpression = condition;
      deleteConfig.ReturnValues = ReturnValues.AllOldAttributes;
      
  Task<Document> delItem = table.DeleteItemAsync( hash, range, deleteConfig );
        deletedItem = await delItem;

Azure Cosmos DB:

In Azure Cosmos DB kunnen we het document ophalen en asynchroon verwijderen:

var result= ReadingMovieItem_async_List_CosmosDB("select * from c where c.info.rating>7 AND c.year=2018 AND c.title='The Big New Movie'");
while (result.HasMoreResults)
{
  var resultModel = await result.ReadNextAsync();
  foreach (var movie in resultModel.ToList<MovieModel>())
  {
    await moviesContainer.DeleteItemAsync<MovieModel>(movie.Id, new PartitionKey(movie.Year));
  }
  }

Query's uitvoeren voor documenten

DynamoDB:

In Amazon DynamoDB zijn API-functies vereist om een query uit te voeren op de gegevens:

QueryOperationConfig config = new QueryOperationConfig( );
  config.Filter = new QueryFilter( );
  config.Filter.AddCondition( "year", QueryOperator.Equal, new DynamoDBEntry[ ] { 1992 } );
  config.Filter.AddCondition( "title", QueryOperator.Between, new DynamoDBEntry[ ] { "B", "Hzz" } );
  config.AttributesToGet = new List<string> { "year", "title", "info" };
  config.Select = SelectValues.SpecificAttributes;
  search = moviesTable.Query( config ); 

Azure Cosmos DB:

In Azure Cosmos DB kunt u projectie uitvoeren en filteren in een eenvoudige SQL-query:

var result = moviesContainer.GetItemQueryIterator<MovieModel>( 
  "select c.Year, c.Title, c.info from c where Year=1998 AND (CONTAINS(Title,'B') OR CONTAINS(Title,'Hzz'))");

Voor bereikbewerkingen, bijvoorbeeld 'between', moet u een scan uitvoeren in Amazon DynamoDB:

ScanRequest sRequest = new ScanRequest
{
  TableName = "Movies",
  ExpressionAttributeNames = new Dictionary<string, string>
  {
    { "#yr", "year" }
  },
  ExpressionAttributeValues = new Dictionary<string, AttributeValue>
  {
      { ":y_a", new AttributeValue { N = "1960" } },
      { ":y_z", new AttributeValue { N = "1969" } },
  },
  FilterExpression = "#yr between :y_a and :y_z",
  ProjectionExpression = "#yr, title, info.actors[0], info.directors, info.running_time_secs"
};

ClientScanning_async( sRequest ).Wait( );

In Azure Cosmos DB kunt u SQL-query en een instructie met één regel gebruiken:

var result = moviesContainer.GetItemQueryIterator<MovieModel>( 
  "select c.title, c.info.actors[0], c.info.directors,c.info.running_time_secs from c where BETWEEN year 1960 AND 1969");

Een container verwijderen

DynamoDB:

Als u de tabel in Amazon DynamoDB wilt verwijderen, kunt u het volgende opgeven:

client.DeleteTableAsync( tableName );

Azure Cosmos DB:

Als u de verzameling in Azure Cosmos DB wilt verwijderen, kunt u het volgende opgeven:

await moviesContainer.DeleteContainerAsync();

Verwijder vervolgens ook de database als u het volgende nodig hebt:

await cosmosDatabase.DeleteAsync();

Zoals u ziet, biedt Azure Cosmos DB ondersteuning voor natuurlijke query's (SQL), zijn bewerkingen asynchroon en veel eenvoudiger. U kunt uw complexe code eenvoudig migreren naar Azure Cosmos DB, wat na de migratie eenvoudiger wordt.

Volgende stappen