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 met lage latentie tot uw gegevens.

In dit artikel wordt beschreven hoe u uw .NET-toepassing migreert van Amazon DynamoDB naar Azure Cosmos DB met minimale codewijzigingen. Zie het overzichtsartikel voor meer informatie over Azure Cosmos DB.

Conceptuele verschillen

De volgende tabel bevat belangrijke conceptuele verschillen tussen Azure Cosmos DB en DynamoDB:

DynamoDB Azure Cosmos DB
Niet van toepassing Gegevensbank
Tabel Verzameling
Artikel Document
Kenmerk Veld
Secondary index Secondary index
Primary key > partition key Partitiesleutel
Primary key > sort key Niet vereist
Stroom Feed wijzigen
Schrijf rekenunit Verzoekseenheid (flexibel, kan worden gebruikt voor lees- en schrijfbewerkingen)
Read compute unit Verzoekseenheid (flexibel, kan worden gebruikt voor lees- en schrijfbewerkingen)
Globale tabel 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

De JSON-structuur van Azure Cosmos DB is eenvoudiger dan de JSON-structuur 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 een essentieel aspect van databasemigratie. De volgende secties vergelijken de code tussen Amazon DynamoDB en Azure Cosmos DB om te begrijpen hoe het migratieproces werkt.

Kloon de volgende opslagplaats om de broncode te downloaden:

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

Vereiste voorwaarden

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

Stel uw code in

Voeg het volgende NuGet-pakket toe aan uw project:

Install-Package Microsoft.Azure.Cosmos

Een verbinding tot stand brengen

DynamoDB

In Amazon DynamoDB gebruikt u de volgende code 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 azure Cosmos DB SQL SDK-connectiviteitsmodi voor meer informatie.

  • ApplicationRegion: Gebruik deze optie om de voorkeursregio voor geo-replicatie in te stellen voor interactie met Azure Cosmos DB. Zie Uw gegevens wereldwijd distribueren met Azure Cosmos DB voor meer informatie.

  • ConsistencyLevel: Gebruik deze optie om het standaardconsistentieniveau te overschrijven. Zie Consistentieniveaus in Azure Cosmos DB voor meer informatie.

  • BulkExecutionMode: Gebruik deze optie om bulkbewerkingen uit te voeren door de AllowBulkExecution eigenschap in te stellen op true. Voor meer informatie, zie Gegevens bulkimporteren naar een Azure Cosmos DB for NoSQL-account met behulp van de .NET SDK.

    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 in Amazon DynamoDB wilt opslaan, moet u eerst de tabel maken. Definieer het schema, het sleuteltype en de kenmerken, 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 en de schrijf-rekeneenheden inrichten. In Azure Cosmos DB geeft u de doorvoer op als aanvraageenheden per seconde (RU/s). U kunt RU/s voor elke bewerking dynamisch gebruiken. De gegevens zijn ingedeeld als database, container en vervolgens item. U kunt de doorvoer opgeven op databaseniveau, op verzamelingsniveau of beide.

Een database maken:

await client_cosmosDB.CreateDatabaseIfNotExistsAsync(movies_table_name);

Een 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 moviesArray code bevat JSON-documenten en vervolgens moet u de JSON-documenten 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 ervoor kiezen om te streamen en te schrijven met behulp van moviesContainer.CreateItemStreamAsync(). In dit voorbeeld wordt de JSON echter gedeserialiseerd in het MovieModel type om de functie typecasting te demonstreren. De code is multithreaded en maakt gebruik van de gedistribueerde architectuur in Azure Cosmos DB om het laden te versnellen.

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 het documenttype gebruikt newItem :

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

Azure Cosmos DB

Azure Cosmos DB biedt typeveiligheid via een gegevensmodel. Dit voorbeeld gebruikt een gegevensmodel genaamd 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 is 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

With Azure Cosmos DB, the query is natural (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 documentverzameling in het vorige voorbeeld is type veilig en biedt een natuurlijke queryoptie.

Een item bijwerken

DynamoDB

Een item bijwerken in Amazon DynamoDB:

updateResponse = await client.UpdateItemAsync( updateRequest );

Azure Cosmos DB

In Azure Cosmos DB wordt een update behandeld als Upsert bewerking (het document invoegen 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 kunt u 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));
  }
  }

Documenten bevragen

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 een 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 indien nodig ook de database:

await cosmosDatabase.DeleteAsync();

Samenvatting

Zoals in de voorgaande voorbeelden wordt weergegeven, ondersteunt Azure Cosmos DB natuurlijke query's (SQL) en zijn bewerkingen asynchroon. U kunt uw complexe code eenvoudig migreren naar Azure Cosmos DB. De code wordt na de migratie eenvoudiger.