Partilhar via


Anexos do Azure Cosmos DB

APLICA-SE A: NoSQL MongoDB

Os anexos do Azure Cosmos DB são itens especiais que contêm referências a metadados associados a um blob externo ou ficheiro de multimédia.

O Azure Cosmos DB suporta dois tipos de anexos:

  • Os Anexos Não Geridos são um wrapper em torno de uma referência de URI a um blob armazenado num serviço externo (por exemplo, Armazenamento do Azure, OneDrive, etc.). Esta abordagem é semelhante ao armazenamento de uma propriedade URI num item padrão do Azure Cosmos DB.
  • Os Anexos Geridos são geridos e armazenados internamente pelos blobs pelo Azure Cosmos DB e expostos através de um mediaLink gerado pelo sistema.

Nota

Os anexos são uma funcionalidade legada. O suporte está no âmbito para oferecer funcionalidades contínuas se já estiver a utilizar esta funcionalidade.

Em vez de utilizar anexos, recomendamos que utilize Armazenamento de Blobs do Azure como um serviço de armazenamento de blobs criado de propósito para armazenar dados de blobs. Pode continuar a armazenar metadados relacionados com blobs, juntamente com ligações URI de referência, no Azure Cosmos DB como propriedades do item. Armazenar estes dados no Azure Cosmos DB proporciona a capacidade de consultar metadados e ligações para blobs armazenados em Armazenamento de Blobs do Azure.

A Microsoft comprometeu-se a fornecer um aviso mínimo de 36 meses antes de preterir totalmente os anexos , que será anunciado numa data adicional.

Limitações conhecidas

Os anexos geridos do Azure Cosmos DB são distintos do suporte para itens padrão, para os quais oferece escalabilidade ilimitada, distribuição global e integração com outros serviços do Azure.

  • Os anexos não são suportados em todas as versões dos SDKs do Azure Cosmos DB.
  • Os anexos geridos estão limitados a 2 GB de armazenamento por conta de base de dados.
  • Os anexos geridos não são compatíveis com a distribuição global do Azure Cosmos DB e não são replicados entre regiões.

Nota

O Azure Cosmos DB para MongoDB versão 3.2 utiliza anexos geridos para GridFS e estes estão sujeitos às mesmas limitações.

Recomendamos aos programadores que utilizem a funcionalidade GridFS do MongoDB definida para atualizar para a versão 3.6 ou superior do Azure Cosmos DB para MongoDB, que é dissociada dos anexos e proporciona uma melhor experiência. Em alternativa, os programadores que utilizam o conjunto de funcionalidades do MongoDB GridFS também devem considerar a utilização de Armazenamento de Blobs do Azure - que é concebido de propósito para armazenar conteúdos de blobs e oferece funcionalidades expandidas a um custo mais baixo em comparação com o GridFS.

Migrar Anexos para Armazenamento de Blobs do Azure

Recomendamos a migração de anexos do Azure Cosmos DB para Armazenamento de Blobs do Azure ao seguir estes passos:

  1. Copie os dados de anexos do contentor do Azure Cosmos DB de origem para o contentor de destino Armazenamento de Blobs do Azure.
  2. Valide os dados de blob carregados no contentor de destino Armazenamento de Blobs do Azure.
  3. Se aplicável, adicione referências de URI aos blobs contidos no Armazenamento de Blobs do Azure como propriedades de cadeia no conjunto de dados do Azure Cosmos DB.
  4. Refatorize o código da aplicação para ler e escrever blobs a partir do novo contentor de Armazenamento de Blobs do Azure.

O seguinte exemplo de código mostra como copiar anexos do Azure Cosmos DB para o armazenamento de Blobs do Azure como parte de um fluxo de migração com o SDK .NET v2 do Azure Cosmos DB e Armazenamento de Blobs do Azure SDK .NET v12. Certifique-se de que substitui o <placeholder values> para a conta do Azure Cosmos DB de origem e o contentor de armazenamento de Blobs do Azure de destino.


using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;

namespace attachments
{
    class Program
    {
        private static string cosmosAccount = "<Your_Azure_Cosmos_account_URI>";
        private static string cosmosKey = "<Your_Azure_Cosmos_account_PRIMARY_KEY>";
        private static string cosmosDatabaseName = "<Your_Azure_Cosmos_database>";
        private static string cosmosCollectionName = "<Your_Azure_Cosmos_collection>";
        private static string storageConnectionString = "<Your_Azure_Storage_connection_string>";
        private static string storageContainerName = "<Your_Azure_Storage_container_name>";
        private static DocumentClient cosmosClient = new DocumentClient(new Uri(cosmosAccount), cosmosKey);
        private static BlobServiceClient storageClient = new BlobServiceClient(storageConnectionString);
        private static BlobContainerClient storageContainerClient = storageClient.GetBlobContainerClient(storageContainerName);

        static void Main(string[] args)
        {
            CopyAttachmentsToBlobsAsync().Wait();
        }

        private async static Task CopyAttachmentsToBlobsAsync()
        {
            Console.WriteLine("Copying Azure Cosmos DB Attachments to Azure Blob Storage ...");

            int totalCount = 0;
            string docContinuation = null;

            // Iterate through each item (document in v2) in the Azure Cosmos DB container (collection in v2) to look for attachments.
            do
            {
                FeedResponse<dynamic> response = await cosmosClient.ReadDocumentFeedAsync(
                    UriFactory.CreateDocumentCollectionUri(cosmosDatabaseName, cosmosCollectionName),
                    new FeedOptions
                    {
                        MaxItemCount = -1,
                        RequestContinuation = docContinuation
                    });
                docContinuation = response.ResponseContinuation;

                foreach (Document document in response)
                {
                    string attachmentContinuation = null;
                    PartitionKey docPartitionKey = new PartitionKey(document.Id);

                    // Iterate through each attachment within the item (if any).
                    do
                    {
                        FeedResponse<Attachment> attachments = await cosmosClient.ReadAttachmentFeedAsync(
                            document.SelfLink,
                            new FeedOptions
                            {
                                PartitionKey = docPartitionKey,
                                RequestContinuation = attachmentContinuation
                            }
                        );
                        attachmentContinuation = attachments.ResponseContinuation;

                        foreach (var attachment in attachments)
                        {
                            // Download the attachment in to local memory.
                            MediaResponse content = await cosmosClient.ReadMediaAsync(attachment.MediaLink);

                            byte[] buffer = new byte[content.ContentLength];
                            await content.Media.ReadAsync(buffer, 0, buffer.Length);

                            // Upload the locally buffered attachment to blob storage
                            string blobId = String.Concat(document.Id, "-", attachment.Id);

                            Azure.Response<BlobContentInfo> uploadedBob = await storageContainerClient.GetBlobClient(blobId).UploadAsync(
                                new MemoryStream(buffer, writable: false),
                                true
                            );

                            Console.WriteLine("Copied attachment ... Item Id: {0} , Attachment Id: {1}, Blob Id: {2}", document.Id, attachment.Id, blobId);
                            totalCount++;

                            // Clean up attachment from Azure Cosmos DB.
                            // Warning: please verify you've succesfully migrated attachments to blog storage prior to cleaning up Azure Cosmos DB.
                            // await cosmosClient.DeleteAttachmentAsync(
                            //     attachment.SelfLink,
                            //     new RequestOptions { PartitionKey = docPartitionKey }
                            // );

                            // Console.WriteLine("Cleaned up attachment ... Document Id: {0} , Attachment Id: {1}", document.Id, attachment.Id);
                        }

                    } while (!string.IsNullOrEmpty(attachmentContinuation));
                }
            }
            while (!string.IsNullOrEmpty(docContinuation));

            Console.WriteLine("Finished copying {0} attachments to blob storage", totalCount);
        }
    }
}

Passos seguintes