Biblioteca de clientes do Azure Cosmos DB para JavaScript – versão 4.0.0

/Máquina

Status de build do selo npm mais recente

O Azure Cosmos DB é um serviço de banco de dados multimodelo globalmente distribuído que dá suporte a bancos de dados de documentos, valor-chave, coluna larga e grafo. Esse pacote destina-se a aplicativos JavaScript/TypeScript para interagir com bancos de dados da API do SQL e os documentos JSON que eles contêm:

  • Criar bancos de dados do Cosmos DB e modificar as configurações
  • Criar e modificar contêineres para armazenar coleções de documentos JSON
  • Criar, ler, atualizar e excluir os itens (documentos JSON) nos contêineres
  • Consultar os documentos no banco de dados usando uma sintaxe semelhante à SQL

Links principais:

Introdução

Pré-requisitos

Assinatura do Azure e conta da API de SQL do Cosmos DB

Você precisa ter uma Assinatura do Azure e uma conta do Cosmos DB (API de SQL) para usar este pacote.

Se você precisar de uma conta da API de SQL do Cosmos DB, use o Azure Cloud Shell para criar uma com este comando da CLI do Azure:

az cosmosdb create --resource-group <resource-group-name> --name <cosmos-database-account-name>

Ou você pode criar uma conta no portal do Azure

NodeJS

Este pacote é distribuído pelo npm que vem pré-instalado com o Node.js. Use o Node v10 ou superior.

CORS

Você precisará configurar regras de CORS (Compartilhamento de Recursos entre Origens) para a conta do Cosmos DB se precisar desenvolver para navegadores. Siga as instruções no documento vinculado para criar regras de CORS para o Cosmos DB.

Instalar este pacote

npm install @azure/cosmos

Obter credenciais da conta

Você precisará do ponto de extremidade e da chave da conta do Cosmos DB. Encontre-os no portal do Azure ou usar o snippet da CLI do Azure abaixo. O snippet é formatado para o shell do Bash.

az cosmosdb show --resource-group <your-resource-group> --name <your-account-name> --query documentEndpoint --output tsv
az cosmosdb keys list --resource-group <your-resource-group> --name <your-account-name> --query primaryMasterKey --output tsv

Criar uma instância de CosmosClient

A interação com o Cosmos BD começa com uma instância da classe CosmosClient

const { CosmosClient } = require("@azure/cosmos");

const endpoint = "https://your-account.documents.azure.com";
const key = "<database account masterkey>";
const client = new CosmosClient({ endpoint, key });

async function main() {
  // The rest of the README samples are designed to be pasted into this function body
}

main().catch((error) => {
  console.error(error);
});

Para simplificar, incluímos key e endpoint diretamente no código, mas você pode carregá-los de um arquivo que não esteja no controle do código-fonte usando um projeto como dotenv ou carregando de variáveis de ambiente

Em ambientes de produção, segredos como chaves devem ser armazenados no Azure Key Vault

Principais conceitos

Depois de inicializar um CosmosClient, você pode interagir com os tipos de recursos primários no Cosmos DB:

  • Banco de dados: Uma conta do Cosmos DB pode conter vários bancos de dados. Ao criar um banco de dados, você especifica a API que quer usar para interagir com os respectivos documentos: SQL, MongoDB, Gremlin, Cassandra ou Tabelas do Azure. Use o objeto de banco de dados para gerenciar os respectivos contêineres.

  • Contêiner: Um contêiner é uma coleção de documentos JSON. Você cria (insere), lê, atualiza e exclui itens em um contêiner usando métodos no objeto de contêiner.

  • Item: um item é um documento JSON armazenado em um contêiner. Cada item precisa incluir uma chave id com um valor que identifique-o exclusivamente dentro do contêiner. Se você não fornecer uma id, o SDK vai gerá-la automaticamente.

Para obter mais informações sobre esses recursos, confira Trabalhar com bancos de dados, contêineres e itens do Azure Cosmos.

Exemplos

As seguintes seções fornecem vários snippets de código que abrangem algumas das tarefas mais comuns do Cosmos DB, incluindo:

Criar um banco de dados

Depois de autenticar o CosmosClient, você pode trabalhar com qualquer recurso na conta. O snippet de código abaixo cria um banco de dados da API NOSQL.

const { database } = await client.databases.createIfNotExists({ id: "Test Database" });
console.log(database.id);

Criar um contêiner

Este exemplo cria um contêiner com configurações padrão

const { container } = await database.containers.createIfNotExists({ id: "Test Database" });
console.log(container.id);

Usando chaves de partição

Este exemplo mostra vários tipos de chaves de partição com suporte.

await container.item("id", "1").read();        // string type
await container.item("id", 2).read();          // number type
await container.item("id", true).read();       // boolean type
await container.item("id", {}).read();         // None type
await container.item("id", undefined).read();  // None type
await container.item("id", null).read();       // null type

Se a Chave de Partição consistir em um único valor, ela poderá ser fornecida como um valor literal ou uma matriz.

await container.item("id", "1").read();
await container.item("id", ["1"]).read();

Se a Chave de Partição consistir em mais de um valor, ela deverá ser fornecida como uma matriz.

await container.item("id", ["a", "b"]).read();
await container.item("id", ["a", 2]).read();
await container.item("id", [{}, {}]).read();
await container.item("id", ["a", {}]).read();
await container.item("id", [2, null]).read();

Inserir itens

Para inserir itens em um contêiner, passe um objeto contendo os dados para Items.upsert. O serviço do Azure Cosmos DB requer que cada item tenha uma id chave. Se você não fornecer uma id, o SDK vai gerá-la automaticamente.

Este exemplo insere vários itens no contêiner

const cities = [
  { id: "1", name: "Olympia", state: "WA", isCapitol: true },
  { id: "2", name: "Redmond", state: "WA", isCapitol: false },
  { id: "3", name: "Chicago", state: "IL", isCapitol: false }
];
for (const city of cities) {
  await container.items.create(city);
}

Ler um item

Para ler um só item de um contêiner, use Item.read. Essa é uma operação mais simples do que usar SQL para consultar por id.

await container.item("1", "1").read();

CRUD no contêiner com chave de partição hierárquica

Criar um contêiner com chave de partição hierárquica

const containerDefinition = {
  id: "Test Database",
  partitionKey: {
    paths: ["/name", "/address/zip"],
    version: PartitionKeyDefinitionVersion.V2,
    kind: PartitionKeyKind.MultiHash,
  },
}
const { container } = await database.containers.createIfNotExists(containerDefinition);
console.log(container.id);

Inserir um item com chave de partição hierárquica definida como - ["/name", "/address/zip"]

const item = {
  id: 1,
  name: 'foo',
  address: {
    zip: 100
  },
  active: true
}
await container.items.create(item);

Para ler um único item de um contêiner com chave de partição hierárquica definida como - ["/name", "/address/zip"],

await container.item("1", ["foo", 100]).read();

Consultar um item com chave de partição hierárquica com chave de partição hierárquica definida como - ["/name", "/address/zip"],

const { resources } = await container.items
  .query("SELECT * from c WHERE c.active = true", {
          partitionKey: ["foo", 100],
        })
  .fetchAll();
for (const item of resources) {
  console.log(`${item.name}, ${item.address.zip} `);
}

Excluir um item

Para excluir itens de um contêiner, use Item.delete.

// Delete the first item returned by the query above
await container.item("1").delete();

Consultar o banco de dados

Um banco de dados da API de SQL do Cosmos DB dá suporte à consulta dos itens em um contêiner com Items.query usando uma sintaxe semelhante à SQL:

const { resources } = await container.items
  .query("SELECT * from c WHERE c.isCapitol = true")
  .fetchAll();
for (const city of resources) {
  console.log(`${city.name}, ${city.state} is a capitol `);
}

Execute consultas parametrizadas passando um objeto contendo os parâmetros e seus valores para Items.query:

const { resources } = await container.items
  .query({
    query: "SELECT * from c WHERE c.isCapitol = @isCapitol",
    parameters: [{ name: "@isCapitol", value: true }]
  })
  .fetchAll();
for (const city of resources) {
  console.log(`${city.name}, ${city.state} is a capitol `);
}

Para obter mais informações de como consultar bancos de dados do Cosmos BD usando a API de SQL, confira Consultar dados do Azure Cosmos DB com consultas SQL.

Modelo de pull do feed de alterações

O feed de alterações pode ser buscado para uma chave de partição, um intervalo de feeds ou um contêiner inteiro.

Para processar o feed de alterações, crie uma instância do ChangeFeedPullModelIterator. Ao criar ChangeFeedPullModelIteratorinicialmente , você deve especificar um valor necessário changeFeedStartFrom dentro do ChangeFeedIteratorOptions que consiste na posição inicial para ler as alterações e o recurso (uma chave de partição ou um FeedRange) para o qual as alterações devem ser buscadas. Opcionalmente, você pode usar maxItemCount em ChangeFeedIteratorOptions para definir o número máximo de itens recebidos por página.

Observação: se nenhum changeFeedStartFrom valor for especificado, o changefeed será buscado para um contêiner inteiro de Now().

Há quatro posições iniciais para o feed de alterações:

  • Beginning
// Signals the iterator to read changefeed from the beginning of time.
const options = {
  changeFeedStartFrom: ChangeFeedStartFrom.Beginning();
}
const iterator = container.getChangeFeedIterator(options);
  • Time
// Signals the iterator to read changefeed from a particular point of time.
const time = new Date("2023/09/11") // some sample date
const options = {
  changeFeedStartFrom: ChangeFeedStartFrom.Time(time);
}
  • Now
// Signals the iterator to read changefeed from this moment onward.
const options = {
  changeFeedStartFrom: ChangeFeedStartFrom.Now();
}
  • Continuation
// Signals the iterator to read changefeed from a saved point.
const continuationToken = "some continuation token recieved from previous request";
const options = {
  changeFeedStartFrom: ChangeFeedStartFrom.Continuation(continuationToken);
}

Aqui está um exemplo de busca de feed de alterações para uma chave de partição

const partitionKey = "some-partition-Key-value";
const options = {
  changeFeedStartFrom: ChangeFeedStartFrom.Beginning(partitionKey),
};

const iterator = container.items.getChangeFeedIterator(options);

while (iterator.hasMoreResults) {
  const response = await iterator.readNext();
  // process this response
}

Como o feed de alterações é efetivamente uma lista infinita de itens que abrangem todas as futuras gravações e atualizações, o valor de hasMoreResults é sempre true. Ao tentar ler o feed de alterações e não houver nenhuma nova alteração disponível, você recebe uma resposta com o status NotModified.

Diretrizes de uso mais detalhadas e exemplos de feed de alterações podem ser encontrados aqui.

Tratamento de erros

O SDK gera vários tipos de erros que podem ocorrer durante uma operação.

  1. ErrorResponse será gerado se a resposta de uma operação retornar um código de erro de >=400.
  2. TimeoutError será gerado se Abort for chamado internamente devido ao tempo limite.
  3. AbortError será gerado se qualquer sinal passado pelo usuário tiver causado a anulação.
  4. RestError é gerado em caso de falha de chamada do sistema subjacente devido a problemas de rede.
  5. Erros gerados por qualquer devDependencies. Por exemplo, @azure/identity O pacote pode gerar CredentialUnavailableError.

Veja a seguir um exemplo de tratamento de erros do tipo ErrorResponse, TimeoutError, AbortErrore RestError.

try {
  // some code
} catch (err) {
  if (err instanceof ErrorResponse) {
    // some specific error handling.
  } else if (err instanceof RestError) {
    // some specific error handling.
  }
  // handle other type of errors in similar way.
  else {
    // for any other error.
  }
}

É importante lidar corretamente com esses erros para garantir que seu aplicativo possa se recuperar normalmente de quaisquer falhas e continuar funcionando conforme o esperado. Mais detalhes sobre alguns desses erros e suas possíveis soluções podem ser encontrados aqui.

Solução de problemas

Geral

Quando você interage com o Cosmos DB, os erros retornados pelo serviço correspondem aos mesmos códigos de status HTTP retornados para as solicitações da API REST:

Códigos de status HTTP para o Azure Cosmos DB

Conflitos

Por exemplo, se você tentar criar um item usando um id que já esteja em uso no banco de dados do Cosmos DB, um erro 409 será retornado, indicando o conflito. No snippet a seguir, o erro é tratado normalmente capturando a exceção e exibindo informações adicionais sobre o erro.

try {
  await containers.items.create({ id: "existing-item-id" });
} catch (error) {
  if (error.code === 409) {
    console.log("There was a conflict with an existing item");
  }
}

Transpilação

Os SDKs do Azure foram projetados para dar suporte à sintaxe ES5 JavaScript e a versões LTS do Node.js. Se você precisar de suporte para runtimes do JavaScript anteriores, como o Internet Explorer ou o Node 6, será necessário transpilar o código do SDK durante o processo de build.

Tratar erros transitórios com novas tentativas

Ao trabalhar com o Cosmos DB, você poderá encontrar falhas transitórias causadas por limites de taxa impostos pelo serviço ou outros problemas transitórios, como interrupções de rede. Para obter informações sobre como lidar com esses tipos de falhas, confira Padrão de repetição no guia Padrões de Design de Nuvem e o padrão de Disjuntor relacionado.

Registro em log

A habilitação do log pode ajudar a descobrir informações úteis sobre falhas. Para ver um log de solicitações e respostas HTTP, defina a variável de ambiente AZURE_LOG_LEVEL como info. Como alternativa, o registro em log pode ser habilitado em runtime chamando setLogLevel no @azure/logger. Ao usar AZURE_LOG_LEVEL , certifique-se de defini-la antes que a biblioteca de registro em log seja inicializada. O ideal é passá-lo pela linha de comando, se estiver usando bibliotecas como, por dotenv exemplo, verifique se essas bibliotecas são inicializadas antes da biblioteca de registro em log.

const { setLogLevel } = require("@azure/logger");
setLogLevel("info");

Para obter instruções mais detalhadas sobre como habilitar logs, veja os documentos do pacote @azure/logger.

Diagnósticos

O recurso de Diagnóstico do Cosmos fornece insights aprimorados sobre todas as operações do cliente. Um objeto CosmosDiagnostics é adicionado à resposta de todas as operações do cliente. tal como

  • Reponse da operação de pesquisa de ponto – item.read(), container.create(), database.delete()
  • Reponse da operação de consulta -queryIterator.fetchAll(),
  • Operações em massa e do Lote -item.batch().
  • Objetos de resposta de erro/exceção.

Um objeto CosmosDiagnostics é adicionado à resposta de todas as operações do cliente. Há 3 níveis de Diagnóstico do Cosmos, informações, depuração e depuração não seguras. Quando apenas as informações são destinadas a sistemas de produção e depuração e depuração não seguras devem ser usadas durante o desenvolvimento e a depuração, pois consomem recursos significativamente mais altos. O nível de Diagnóstico do Cosmos pode ser definido de duas maneiras

  • Programaticamente
  const client = new CosmosClient({ endpoint, key, diagnosticLevel: CosmosDbDiagnosticLevel.debug });
  • Usando variáveis de ambiente. (O nível de diagnóstico definido pela variável de ambiente tem prioridade mais alta sobre a configuração por meio de opções de cliente.)
  export AZURE_COSMOSDB_DIAGNOSTICS_LEVEL="debug"

O Diagnóstico do Cosmos tem três membros

  • Tipo ClientSideRequestStatistics: contém detalhes de diagnóstico de agregações, incluindo pesquisas de metadados, repetições, pontos de extremidade contatados e estatísticas de solicitação e resposta, como tamanho e duração do conteúdo. (é sempre coletado, pode ser usado em sistemas de produção.)

  • DiagnosticNode: é uma estrutura semelhante a uma árvore que captura informações detalhadas de diagnóstico. Semelhante à har gravação presente em navegadores. Esse recurso é desabilitado por padrão e destina-se apenas à depuração de ambientes de não produção. (coletado no nível de diagnóstico depuração e depuração não seguro)

  • ClientConfig: captura informações essenciais relacionadas às definições de configuração do cliente durante a inicialização do cliente. (coletado no nível de diagnóstico depuração e depuração não seguro)

Certifique-se de nunca definir o nível de diagnóstico como debug-unsafe no ambiente de produção, pois esse nível CosmosDiagnostics captura os conteúdos de solicitação e resposta e se você optar por registrá-lo (ele é registrado por padrão no @azure/loggerverbose nível). Essas cargas podem ser capturadas em seus coletores de log.

Consumindo diagnósticos

  • Como diagnostics é adicionado a todos os objetos Response. Você pode acessar CosmosDiagnostic programaticamente da seguinte maneira.
  // For point look up operations
  const { container, diagnostics: containerCreateDiagnostic } =
    await database.containers.createIfNotExists({
      id: containerId,
      partitionKey: {
        paths: ["/key1"],
      },
  });

  // For Batch operations
   const operations: OperationInput[] = [
    {
      operationType: BulkOperationType.Create,
      resourceBody: { id: 'A', key: "A", school: "high" },
    },
  ];
  const response = await container.items.batch(operations, "A"); 
  
  // For query operations
  const queryIterator = container.items.query("select * from c");
  const { resources, diagnostics } = await queryIterator.fetchAll();

  // While error handling
  try {
    // Some operation that might fail
  } catch (err) {
    const diagnostics = err.diagnostics
  }
  • Você também pode fazer logon diagnostics usando @azure/logger, o diagnóstico é sempre registrado usando @azure/logger no verbose nível . Portanto, se você definir o nível de diagnóstico como debug ou debug-unsafe e @azure/logger o nível como verbose, diagnostics será registrado em log.

Próximas etapas

Mais códigos de exemplo

vários exemplos disponíveis para você no repositório do SDK no GitHub. Esses exemplos fornecem códigos de exemplo para cenários adicionais que geralmente são encontrados ao trabalhar com o Cosmos DB:

  • Operações de Banco de dados
  • Operações de Contêiner
  • Operações de item
  • Configuração da indexação
  • Leitura do feed de alterações de um contêiner
  • Procedimentos armazenados
  • Alteração das configurações de taxa de transferência de banco de dados/contêiner
  • Operações de gravação em várias regiões

Limitações

Atualmente, não há suporte para os recursos abaixo. Para opções alternativas, marcar a seção Soluções alternativas abaixo.

Limitações do plano de dados:

  • Consultas com COUNT de uma subconsulta DISTINCT
  • Acesso direto ao modo TCP
  • As consultas agregadas entre partições, como classificação, contagem e distintas, não dão suporte a tokens de continuação. Consultas que podem ser transmitidas, como SELECT * FROM WHERE , dá suporte a tokens de continuação. Consulte a seção "Solução alternativa" para executar consultas não transmitíveis sem um token de continuação.
  • Feed de Alterações: Processador
  • Feed de Alterações: ler valores de chave de várias partições
  • Modelo de pull do Feed de Alterações todas as versões e modo de exclusão nº 27058
  • Suporte ao modelo de pull do Feed de Alterações para chaves de partição hierárquicas parciais nº 27059
  • ORDER BY entre partições para tipos mistos
  • Limitações do painel de controle:

    • Obter métricas CollectionSizeUsage, DatabaseUsage e DocumentUsage
    • Criar índice geoespacial
    • Atualizar a taxa de transferência de dimensionamento automático

    Soluções Alternativas

    Token de continuação para consultas entre partições

    Você pode obter consultas entre partições com suporte de token de continuação usando o padrão side car. Esse padrão também pode habilitar aplicativos para serem compostos por tecnologias e componentes heterogêneos.

    Executando uma consulta de partição cruzada não extenuável

    Para executar consultas não transmitíveis sem o uso de tokens de continuação, você pode criar um iterador de consulta com a especificação e as opções de consulta necessárias. O código de exemplo a seguir demonstra como usar um iterador de consulta para buscar todos os resultados sem a necessidade de um token de continuação:

    const querySpec = {
      query: "SELECT * FROM c WHERE c.status = @status",
      parameters: [{ name: "@status", value: "active" }],
    };
    const queryOptions = {
      maxItemCount: 10, // maximum number of items to return per page
      enableCrossPartitionQuery: true,
    };
    const querIterator = await container.items.query(querySpec, queryOptions);
    while (querIterator.hasMoreResults()) {
      const { resources: result } = await querIterator.fetchNext();
      //Do something with result
    }
    

    Essa abordagem também pode ser usada para consultas que podem ser transmitidas.

    Operações do Painel de Controle

    Normalmente, você pode usar o Portal do Azure, a API REST do Provedor de Recursos do Azure Cosmos DB, a CLI do Azure ou o PowerShell para as limitações sem suporte do painel de controle.

    Documentação adicional

    Para obter uma documentação mais abrangente sobre o serviço Cosmos BD, confira a documentação do Azure Cosmos DB em docs.microsoft.com.

    Contribuição

    Se você quiser contribuir com essa biblioteca, leia o guia de contribuição para saber como criar e testar o código.

    Impressões