Como usar o armazenamento de Tabela do Azure ou o Azure Cosmos DB para Tabela do Node.js

APLICA-SE A: Tabela

Gorjeta

O conteúdo deste artigo aplica-se ao armazenamento de Tabela do Azure e ao Azure Cosmos DB para Tabela. A API for Table é uma oferta premium para armazenamento de tabelas que oferece tabelas otimizadas para taxa de transferência, distribuição global e índices secundários automáticos.

Este artigo mostra como criar tabelas, armazenar seus dados e executar operações CRUD nesses dados. As amostras são escritas em Node.js.

Criar uma conta de serviço do Azure

Você pode trabalhar com tabelas usando o armazenamento de tabela do Azure ou o Azure Cosmos DB. Para saber mais sobre as diferenças entre as ofertas de tabela nesses dois serviços, consulte a Visão geral da API para tabela. Terá de criar uma conta para o serviço que quer utilizar. As seções a seguir mostram como criar o armazenamento de tabela do Azure e a conta do Azure Cosmos DB, no entanto, você pode usar apenas um deles.

Criar uma conta de armazenamento do Azure

A maneira mais fácil de criar uma conta de armazenamento do Azure é usando o portal do Azure. Para saber mais, veja Criar uma conta de armazenamento.

Também pode criar uma conta de armazenamento do Azure com o Azure PowerShell ou a CLI do Azure.

Se preferir não criar uma conta de armazenamento neste momento, você também pode usar o Emulador de Armazenamento do Azure para executar e testar seu código em um ambiente local. Para obter mais informações, consulte Usar o emulador de armazenamento do Azure para desenvolvimento e teste.

Criar uma conta do Azure Cosmos DB para Tabela

Para obter instruções sobre como criar uma conta do Azure Cosmos DB for Table, consulte Criar uma conta de banco de dados.

Configurar seu aplicativo para acessar o Armazenamento de Tabela

Para usar o Armazenamento do Azure ou o Azure Cosmos DB, você precisa do SDK de Tabelas do Azure para Node.js, que inclui um conjunto de bibliotecas de conveniência que se comunicam com os serviços REST de armazenamento.

Utilize o NPM (Node Package Manager, Gestor de Pacotes do Nó) para instalar o pacote

  1. Utilize uma interface de linha de comandos, como o PowerShell (Windows), Terminal (Mac) ou Bash (Unix) e navegue para a pasta onde criou a aplicação.
  2. Digite o seguinte na janela de comando:
   npm install @azure/data-tables
  1. Pode executar manualmente o comando ls para verificar se foi criada uma pasta node_modules. Dentro dessa pasta você encontrará o pacote @azure/data-tables , que contém as bibliotecas que você precisa para acessar tabelas.

Importar o pacote

Adicione o seguinte código ao início do ficheiro server.js na sua aplicação:

const { TableServiceClient, TableClient, AzureNamedKeyCredential, odata } = require("@azure/data-tables");

Ligar ao serviço Tabela do Azure

Você pode se conectar à conta de armazenamento do Azure ou à conta do Azure Cosmos DB for Table. Obtenha a chave compartilhada ou a cadeia de conexão com base no tipo de conta que você está usando.

Criando o cliente de serviço de tabela a partir de uma chave compartilhada

O módulo do Azure lê as variáveis de ambiente AZURE_ACCOUNT e AZURE_ACCESS_KEY e AZURE_TABLES_ENDPOINT para obter as informações necessárias para se conectar à sua conta de Armazenamento do Azure ou ao Azure Cosmos DB. Se essas variáveis de ambiente não estiverem definidas, você deverá especificar as informações da conta ao chamar TableServiceClient. Por exemplo, o código a seguir cria um TableServiceClient objeto:

const endpoint = "<table-endpoint-uri>";
const credential = new AzureNamedKeyCredential(
  "<account-name>",
  "<account-key>"
);

const tableService = new TableServiceClient(
  endpoint,
  credential
);

Criando o cliente de serviço de tabela a partir de uma cadeia de conexão

Para adicionar uma conexão de conta do Azure Cosmos DB ou de armazenamento, crie um TableServiceClient objeto e especifique o nome da conta, a chave primária e o ponto de extremidade. Você pode copiar esses valores da Cadeia>de Conexão de Configurações no portal do Azure para sua conta do Azure Cosmos DB ou conta de Armazenamento. Por exemplo:

const tableService = TableServiceClient.fromConnectionString("<connection-string>");

Criar uma tabela

A chamada para createTable cria uma nova tabela com o nome especificado, se ainda não existir. O exemplo seguinte cria uma nova tabela chamada "mytable", se ainda não existir:

await tableService.createTable('<table-name>');

Criando o cliente Table

Para interagir com uma tabela, você deve criar um TableClient objeto usando as mesmas credenciais usadas para criar o TableServiceClient. O TableClient também requer o nome da tabela de destino.

const tableClient = new TableClient(
  endpoint,
  '<table-name>',
  credential
);

Adicionar uma entidade a uma tabela

Para adicionar uma entidade, crie primeiro um objeto que defina as propriedades da sua entidade. Todas as entidades devem conter partitionKeye rowKey, que são identificadores exclusivos para a entidade.

  • partitionKey - Determina a partição na qual a entidade está armazenada.
  • rowKey - Identifica exclusivamente a entidade dentro da partição.

Tanto partitionKey quanto rowKey devem ser valores de cadeia de caracteres.

Segue-se um exemplo de definição de uma entidade. O dueDate é definido como um tipo de Date. A especificação do tipo é opcional. Se não forem especificados, os tipos são inferidos.

const task = {
  partitionKey: "hometasks",
  rowKey: "1",
  description: "take out the trash",
  dueDate: new Date(2015, 6, 20)
};

Nota

Há também um Timestamp campo para cada registro, que é definido pelo Azure quando uma entidade é inserida ou atualizada.

Para adicionar uma entidade à sua tabela, passe o objeto de entidade para o createEntity método.

let result = await tableClient.createEntity(task);
    // Entity create

Se a operação for bem-sucedida, result contém o ETag e informações sobre a operação.

Resposta de exemplo:

{ 
  clientRequestId: '94d8e2aa-5e02-47e7-830c-258e050c4c63',
  requestId: '08963b85-1002-001b-6d8c-12ae5d000000',
  version: '2019-02-02',
  date: 2022-01-26T08:12:32.000Z,
  etag: `W/"datetime'2022-01-26T08%3A12%3A33.0180348Z'"`,
  preferenceApplied: 'return-no-content',
  'cache-control': 'no-cache',
  'content-length': '0'
}

Atualizar uma entidade

Os diferentes modos updateEntity e upsertEntity métodos

  • Mesclar: atualiza uma entidade atualizando as propriedades da entidade sem substituir a entidade existente.
  • Substituir: atualiza uma entidade existente substituindo a entidade inteira.

O exemplo a seguir demonstra a atualização de uma entidade usando upsertEntity:

// Entity doesn't exist in table, so calling upsertEntity will simply insert the entity.
let result = await tableClient.upsertEntity(task, "Replace");

Se a entidade que está sendo atualizada não existir, a operação de atualização falhará; Portanto, se você quiser armazenar uma entidade independentemente de ela já existir, use upsertEntity.

O result para operações de atualização com êxito contém o Etag da entidade atualizada.

Trabalhar com grupos de entidades

Por vezes, é útil submeter várias operações em conjunto num batch, para garantir um processamento atómico pelo servidor. Para fazer isso, crie uma matriz de operações e passe-a para o submitTransaction método em TableClient.

O exemplo seguinte demonstra como submeter duas entidades num batch:

const task1 = {
  partitionKey: "hometasks",
  rowKey: "1",
  description: "Take out the trash",
  dueDate: new Date(2015, 6, 20)
};
const task2 = {
  partitionKey: "hometasks",
  rowKey: "2",
  description: "Wash the dishes",
  dueDate: new Date(2015, 6, 20)
};

const tableActions = [
  ["create", task1],
  ["create", task2]
];

let result = await tableClient.submitTransaction(tableActions);
    // Batch completed

Para operações batch de êxito, result contém informações para cada operação no batch.

Obter uma entidade por chave

Para retornar uma entidade específica com base em PartitionKey e RowKey, use o método getEntity .

let result = await tableClient.getEntity("hometasks", "1")
  .catch((error) => {
    // handle any errors
  });
  // result contains the entity

Depois de concluir a operação, result contém a entidade.

Consultar um conjunto de entidades

O exemplo a seguir cria uma consulta que retorna os cinco principais itens com uma PartitionKey de 'hometasks' e lista todas as entidades na tabela.

const topN = 5;
const partitionKey = "hometasks";

const entities = tableClient.listEntities({
  queryOptions: { filter: odata`PartitionKey eq ${partitionKey}` }
});

let topEntities = [];
const iterator = entities.byPage({ maxPageSize: topN });

for await (const page of iterator) {
  topEntities = page;
  break;
}

// Top entities: 5
console.log(`Top entities: ${topEntities.length}`);

// List all the entities in the table
for await (const entity of entities) {
console.log(entity);
}

Consultar um subconjunto de propriedades de entidade

Uma consulta a uma tabela pode obter apenas alguns campos de uma entidade. Isto reduz a largura de banda e pode melhorar o desempenho da consulta, especialmente para entidades grandes. Utilize a cláusula select e transmita os nomes dos campos a devolver. Por exemplo, a consulta seguinte devolve apenas os campos description e dueDate.

const topN = 5;
const partitionKey = "hometasks";

const entities = tableClient.listEntities({
  queryOptions: { filter: odata`PartitionKey eq ${partitionKey}`,
                  select: ["description", "dueDate"]  }
});

let topEntities = [];
const iterator = entities.byPage({ maxPageSize: topN });

for await (const page of iterator) {
  topEntities = page;
  break;
}

Eliminar uma entidade

Pode eliminar uma entidade ao utilizar as chaves de partição e linha. Neste exemplo, o objeto task1 contém os valores rowKey e partitionKey da entidade a ser excluída. Em seguida, o objeto é transmitido ao método deleteEntity.

const tableClient = new TableClient(
  tablesEndpoint,
  tableName,
  new AzureNamedKeyCredential("<accountName>", "<accountKey>")
);

await tableClient.deleteEntity("hometasks", "1");
    // Entity deleted

Nota

Considere utilizar ETags quando eliminar itens para se certificar de que o item não foi modificado por outro processo. Consulte Atualizar uma entidade para obter informações sobre como utilizar ETags.

Eliminar uma tabela

O código seguinte elimina uma tabela de uma conta de armazenamento.

await tableClient.deleteTable(mytable);
        // Table deleted

Utilizar tokens de continuação

Quando estiver a consultar tabelas para grandes quantidades de resultados, procure os tokens de continuação. Poderão existir grandes quantidades de dados disponíveis para a consulta que podem passar despercebidos caso não efetue a compilação para determinar a existência de um token de continuação.

O objeto results devolvido durante a consulta de entidades define uma propriedade continuationToken quando um token desse tipo existe. Pode então utilizá-lo quando executar uma consulta para continuar a percorrer as entidades da partição e da tabela.

Durante a consulta, pode fornecer um parâmetro continuationToken entre a instância do objeto de consulta e a função de chamada de retorno:

let iterator = tableClient.listEntities().byPage({ maxPageSize: 2 });
let interestingPage;

const page = await tableClient
   .listEntities()
   .byPage({ maxPageSize: 2, continuationToken: interestingPage })
   .next();

 if (!page.done) {
   for (const entity of page.value) {
     console.log(entity.rowKey);
   }
 }

Trabalhar com assinaturas de acesso partilhado

As assinaturas de acesso partilhado (SAS) são uma forma segura de fornecer acesso granular às tabelas sem fornecer o nome ou a chaves da sua conta de Armazenamento. As SAS são frequentemente utilizadas para fornecer acesso limitado aos seus dados, tal como permitir que uma aplicação móvel consulte registos.

Um aplicativo confiável, como um serviço baseado em nuvem, gera uma SAS usando o generateTableSas do TableClient e a fornece a um aplicativo não confiável ou semiconfiável, como um aplicativo móvel. A SAS é gerada utilizando uma política, que descreve as datas de início e de fim durante as quais a SAS é válida, bem como o nível de acesso concedido ao titular da SAS.

O exemplo a seguir gera uma nova política de acesso compartilhado que permitirá que o titular do SAS consulte ('r') a tabela.

const tablePermissions = {
    query: true
// Allows querying entities
};

// Create the table SAS token
const tableSAS = generateTableSas('mytable', cred, {
  expiresOn: new Date("2022-12-12"),
  permissions: tablePermissions
});

Em seguida, o aplicativo cliente usa a SAS com AzureSASCredential para executar operações na tabela. O exemplo seguinte liga-se à tabela e executa uma consulta. Consulte o artigo Conceder acesso limitado aos recursos do Armazenamento do Azure usando assinaturas de acesso compartilhado (SAS) para obter o formato de tableSAS.

// Note in the following command, tablesUrl is in the format: `https://<your_storage_account_name>.table.core.windows.net` and the tableSAS is in the format: `sv=2018-03-28&si=saspolicy&tn=mytable&sig=9aCzs76n0E7y5BpEi2GvsSv433BZa22leDOZXX%2BXXIU%3D`;

const tableService = new TableServiceClient(tablesUrl, new AzureSASCredential(tableSAS));
const partitionKey = "hometasks";

const entities = tableService.listTables({
  queryOptions: { filter: odata`PartitionKey eq ${partitionKey}` }
});

Como a SAS foi gerada com acesso apenas de consulta, é devolvido um erro se tentar inserir, atualizar ou eliminar entidades.

Listas de Controlo de Acesso

Também pode utilizar uma Lista de Controlo de Acesso (ACL) para definir a política de acesso para uma SAS. Isto é útil se pretender permitir que os vários clientes acedam à tabela, mas cada cliente deva ter uma política de acesso diferente.

Uma ACL é implementada com uma matriz de políticas de acesso, com um ID associado a cada política. O exemplo seguinte define duas políticas, uma para "user1" e outra para "user2":

var sharedAccessPolicy = [{
  id:"user1",
  accessPolicy:{
    permission: "r" ,
    Start: startsOn,
    Expiry: expiresOn,
  }},
  {
  id:"user2",
  accessPolicy:{
    permissions: "a",
    Start: startsOn,
    Expiry: expiresOn,
  }},
]

O exemplo a seguir obtém a ACL atual para a tabela hometasks e adiciona as novas políticas usando setAccessPolicy. Esta abordagem permite:

tableClient.getAccessPolicy();
tableClient.setAccessPolicy(sharedAccessPolicy);

Depois de definir a ACL, pode criar uma SAS com base no ID de uma política. O exemplo seguinte cria uma nova SAS para "user2":

tableSAS = generateTableSas("hometasks",cred,{identifier:'user2'});

Próximos passos

Para obter mais informações, consulte os seguintes recursos.