Partilhar via


Biblioteca de cliente do Azure Cosmos DB para JavaScript - versão 4.2.0

/TypeScript

emblema npm mais recente Status de compilação

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

  • Criar bancos de dados do Cosmos DB e modificar suas configurações
  • Criar e modificar contêineres para armazenar coleções de documentos JSON
  • Criar, ler, atualizar e excluir os itens (documentos JSON) em seus contêineres
  • Consultar os documentos em seu banco de dados usando sintaxe semelhante a SQL

Ligações principais:

Primeiros passos

Pré-requisitos

Subscrição do Azure e Conta de API SQL do Cosmos DB

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

Se você precisar de uma conta da API SQL do Cosmos DB, poderá usar o do 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 via npm que vem pré-instalado com NodeJS usando uma versão LTS.

CORS

Você precisa configurar regras de de compartilhamento de recursos entre origens (CORS) para sua conta do Cosmos DB se precisar desenvolver para navegadores. Siga as instruções no documento vinculado para criar novas regras CORS para seu Cosmos DB.

Instalar este pacote

npm install @azure/cosmos

Obter credenciais de conta

Você precisará do seu Cosmos DB Account Endpoint e Key. Você pode encontrá-los no do Portal do Azure ou usar o trecho de da CLI do Azure abaixo. O trecho é formatado para o shell 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 DB 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 os key e endpoint diretamente no código, mas você provavelmente desejará 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 em Cofre de Chaves do Azure

Conceitos-chave

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

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

  • Container: 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 Container.

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

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

Exemplos

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

Criar uma base de dados

Depois de autenticar seu CosmosClient, você pode trabalhar com qualquer recurso na conta. O trecho de código abaixo cria um banco de dados de 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 suportadas.

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 que contém seus dados para Items.upsert. O serviço Azure Cosmos DB requer que cada item tenha uma chave de id. Se você não fornecer um, o SDK gerará um id 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 único item de um contêiner, use Item.read. Esta é uma operação menos dispendiosa 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 a base de dados

Um banco de dados Cosmos DB SQL API oferece suporte à consulta de itens em um contêiner com Items.query usando sintaxe semelhante a 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 sobre como consultar bancos de dados do Cosmos DB usando a API SQL, consulte Consultar dados do Azure Cosmos DB com consultas SQL.

Alterar modelo de receção de alimentação

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

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

Nota: Se nenhum valor de changeFeedStartFrom for especificado, o changefeed será buscado para um contêiner inteiro de Now().

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

  • 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 como buscar feed de alteração 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 engloba todas as gravações e atualizações futuras, o valor de hasMoreResults é sempre true. Quando você tenta ler o feed de alterações e não há novas alterações disponíveis, você recebe uma resposta com NotModified status.

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 é lançado se a resposta de uma operação retorna um código de erro de >= 400.
  2. TimeoutError é lançado se Abort for chamado internamente devido ao tempo limite.
  3. AbortError é lançado se algum usuário passou sinal causou o abortamento.
  4. RestError é lançado em caso de falha da chamada do sistema subjacente devido a problemas de rede.
  5. Erros gerados por quaisquer devDependencies. por exemplo. @azure/identity pacote poderia lançar CredentialUnavailableError.

Segue-se um exemplo para lidar com 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 solicitações de 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á está em uso no banco de dados do Cosmos DB, um erro de 409 será retornado, indicando o conflito. No trecho 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 JavaScript do ES5 e às versões LTS do Node.js. Se você precisar de suporte para tempos de execução JavaScript anteriores, como o Internet Explorer ou o Nó 6, precisará transpilar o código do SDK como parte do processo de compilação.

Lidar com erros transitórios com novas tentativas

Ao trabalhar com o Cosmos DB, você pode encontrar falhas transitórias causadas por limites de taxa de 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, consulte de padrão de repetição no guia Padrões de design de nuvem e o padrão de disjuntor de relacionado.

Registo

Habilitar o registro em 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 tempo de execução chamando setLogLevel no @azure/logger. Ao usar AZURE_LOG_LEVEL certifique-se de defini-lo antes que a biblioteca de log seja inicializada. O ideal é passá-lo pela linha de comando, se estiver usando bibliotecas como dotenv certifique-se de que essas bibliotecas sejam inicializadas antes de registrar a biblioteca.

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

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

Diagnóstico

O recurso Cosmos Diagnostics fornece informações aprimoradas sobre todas as operações do seu cliente. Um objeto CosmosDiagnostics é adicionado à resposta de todas as operações do cliente. tais como:

  • Ponto de pesquisa operação reponse - item.read(), container.create(), database.delete()
  • Resposta da operação de consulta -queryIterator.fetchAll(),
  • Operações a granel e em lote -item.batch().
  • Objetos de resposta de erro/exceção.

Um objeto CosmosDiagnostics é adicionado à resposta de todas as operações do cliente. Existem 3 níveis de diagnóstico Cosmos, info, debug e debug-unsafe. Onde apenas as informações são destinadas a sistemas de produção e depuração e depuração-insegura devem ser usados durante o desenvolvimento e depuração, uma vez que consomem recursos significativamente maiores. O nível de diagnóstico do Cosmos pode ser definido de 2 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 Ambiente tem maior prioridade sobre a configuração por meio das opções do cliente.)
  export AZURE_COSMOSDB_DIAGNOSTICS_LEVEL="debug"

O Cosmos Diagnostic tem três membros:

  • Tipo de ClientSideRequestStatistics: Contém detalhes de diagnóstico agregados, incluindo pesquisas de metadados, tentativas, pontos de extremidade contatados e estatísticas de solicitação e resposta, como tamanho e duração da carga útil. (é sempre coletado, pode ser usado em sistemas de produção.)

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

  • 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 debug e debug-unsafe)

Certifique-se de nunca definir o nível de diagnóstico para debug-unsafe no ambiente de produção, uma vez que este nível CosmosDiagnostics captura cargas úteis de solicitação e resposta e, se você optar por registrá-lo (por padrão, é registrado por @azure/logger no nível verbose). Essas cargas úteis podem ser capturadas em seus coletores de log.

Consumindo diagnósticos

  • Uma vez que diagnostics é adicionado a todos os objetos Response. Você pode acessar programaticamente CosmosDiagnostic 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 registrar diagnostics usando @azure/logger, o diagnóstico é sempre registrado usando @azure/logger no nível verbose. Portanto, se você definir o nível de diagnóstico como debug ou debug-unsafe e @azure/logger nível como verbose, diagnostics serão registrados.

Próximos passos

Mais código de exemplo

Vários exemplos estão disponíveis para você no repositório GitHub do SDK. Estes exemplos fornecem código de exemplo para cenários adicionais comumente encontrados ao trabalhar com o Cosmos DB:

  • Operações de banco de dados
  • Operações de Contentores
  • Operações de item
  • Configurando a indexação
  • Lendo um contêiner Alterar feed
  • Procedimentos armazenados
  • Alterando as 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, os recursos abaixo não são suportados. Para opções alternativas, verifique 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 distinção, não suportam tokens de continuação. Consultas streamable, como SELECT * FROM WHERE , suporta tokens de continuação. Consulte a seção "Solução alternativa" para executar consultas não passíveis de streaming sem um token de continuação.
  • Alterar alimentação: processador
  • Alterar feed: ler vários valores de chave de partições
  • Alterar o suporte do modelo de pull de feed para chaves de partição hierárquicas parciais #27059
  • Partição cruzada ORDER BY para tipos mistos
  • Limitações do plano de controle:

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

    Soluções alternativas

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

    Você pode obter consultas entre partições com suporte a token de continuação usando padrão de carro lateral. Esse padrão também pode permitir que os aplicativos sejam compostos por componentes e tecnologias heterogêneos.

    Executando consulta de partição cruzada não trêmula

    Para executar consultas não streamá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 c.status, COUNT(c.id) AS count FROM c GROUP BY c.status",
    };
    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 streamable.

    Operações do avião de controlo

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

    Documentação adicional

    Para obter documentação mais extensa sobre o serviço Cosmos DB, consulte o de documentação do Azure Cosmos DB no docs.microsoft.com.

    Contribuição

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

    Impressões