Como usar o Armazenamento de Tabelas do Azure e ou o Azure Cosmos DB for Table no Node.js
APLICA-SE AO: Table
Dica
O conteúdo deste artigo se aplica ao Armazenamento de Tabelas do Azure e ao Azure Cosmos DB for Table. A API for Table é uma oferta premium para armazenamento de tabelas que oferece tabelas com taxa de transferência otimizada, distribuição global e índices secundários automáticos.
Este artigo mostra como criar tabelas, armazenar dados e realizar 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 Tabelas do Azure ou o Azure Cosmos DB. Para saber mais sobre as diferenças entre as ofertas de tabela desses dois serviços, confira a Visão geral da API para tabela. Você precisará criar uma conta para o serviço que pretende usar. As seções a seguir mostram como criar as contas do Armazenamento de Tabelas do Azure e do Azure Cosmos DB, no entanto, você pode usar apenas um deles.
Crie 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, consulte Criar uma conta de armazenamento.
Você também pode criar uma conta de armazenamento do Azure usando o Azure PowerShell ou a CLI do Azure.
Se você preferir não criar uma conta de armazenamento no momento, também poderá usar o Emulador de Armazenamento do Azure para executar e testar o seu código em um ambiente local. Para saber mais, confira Usar o Emulador de Armazenamento do Azure para desenvolvimento e teste.
Criar uma conta do Azure Cosmos DB for Table
Para obter instruções sobre como criar uma conta do Azure Cosmos DB for Table, veja Criar uma conta de banco de dados.
Configurar o aplicativo para acessar o Armazenamento de Tabelas
Para usar o Armazenamento do Microsoft Azure ou o Azure Cosmos DB, você precisa do SDK das Tabelas do Azure para Node.js, que inclui um conjunto de bibliotecas de conveniência que comunicam-se com os serviços REST de Armazenamento.
Usar o NPM (Gerenciador de Pacotes de Nós) para obter o pacote
- Use uma interface de linha de comando, como PowerShell (Windows), Terminal (Mac) ou Bash (Unix), e navegue até a pasta em que você criou o aplicativo.
- Digite o seguinte na janela de comando:
npm install @azure/data-tables
- Você pode executar manualmente o comando ls para verificar se uma pasta node_modules foi criada. Dentro dessa pasta, você encontrará o pacote @azure/data-tables que contém as bibliotecas necessárias para acessar as tabelas.
Importar o pacote
Adicione o código a seguir à parte superior do arquivo server.js em seu aplicativo:
const { TableServiceClient, TableClient, AzureNamedKeyCredential, odata } = require("@azure/data-tables");
Conectar-se ao serviço Tabela do Azure
Você pode se conectar à conta de armazenamento do Azure ou à conta do Azure Cosmos DB for Table. Obtenha as credenciais com base no tipo de conta que você está usando.
Criar o cliente do serviço Tabela
O código a seguir cria um objeto TableServiceClient
usando uma credencial do tipo TokenCredential
. A classe DefaultAzureCredential
cria uma credencial de token encadeada que funciona para a maioria dos aplicativos que usam o SDK do Azure, experimentando vários tipos de credenciais. Para obter mais informações, consulte DefaultAzureCredential
.
const credential: TokenCredential = new DefaultAzureCredential();
const tableService = new TableServiceClient(
new Uri("<table-endpoint>"),
credential
);
Criar uma tabela
A chamada para createTable
criará uma tabela com o nome especificado, se ela ainda não existir. O exemplo a seguir criará uma nova tabela denominada 'mytable' se ele ainda não existir:
await tableService.createTable('<table-name>');
Criar o cliente de tabela
Para interagir com uma tabela, crie um objeto TableClient
usando as mesmas credenciais que foram usadas para criar TableServiceClient
. O nome da tabela de destino também é necessário para TableClient
.
const tableClient = new TableClient(
endpoint,
'<table-name>',
credential
);
Adicionar uma entidade a uma tabela
Para adicionar uma entidade, primeiro crie um objeto que defina as propriedades da entidade. Todas as entidades devem conter uma partitionKey e rowKey, que são identificadores exclusivos da entidade.
- partitionKey – Determina a partição na qual a entidade está armazenada.
- rowKey – identifica exclusivamente a entidade dentro da partição.
Ambas, partitionKey e rowKey, devem ser valores de cadeia de caracteres.
A seguir, um exemplo de definição de uma entidade. O dueDate é definido como um tipo de Date
. A especificação do tipo é opcional, e os tipos são inferidos, se não forem especificados.
const task = {
partitionKey: "hometasks",
rowKey: "1",
description: "take out the trash",
dueDate: new Date(2015, 6, 20)
};
Observação
Existe também um campo Timestamp
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 método createEntity
.
let result = await tableClient.createEntity(task);
// Entity create
Se a operação for realizada com sucesso, result
conterá a Etag e as 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 para os métodos updateEntity
e upsertEntity
- Mesclar: atualiza uma entidade atualizando as propriedades da entidade sem substituir a entidade existente.
- Substituir: atualiza uma entidade existente substituindo toda a entidade.
O seguinte exemplo 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 sua existência, use upsertEntity
.
O result
de operações de atualização bem-sucedidas conterá o Etag da entidade atualizada.
Trabalhar com grupos de entidades
Às vezes, convém enviar várias operações juntas em um lote para garantir o processamento atômico pelo servidor. Para fazer isso, crie uma matriz de operações e passe-a para o método submitTransaction
em TableClient
.
O exemplo a seguir demonstra o envio de duas entidades em um lote:
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 em lote bem-sucedidas, result
conterá informações para cada operação no lote.
Recuperar 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
Quando essa operação for concluída, result
conterá a entidade.
Consultar um conjunto de entidades
O exemplo a seguir compila 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 da entidade
Uma consulta a uma tabela pode recuperar apenas alguns campos de uma entidade. Isso reduz a largura de banda e pode melhorar o desempenho da consulta, principalmente em grandes entidades. Use a cláusula select e transmita os nomes dos campos a serem retornados. Por exemplo, a consulta a seguir retorna 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;
}
Excluir uma entidade
Você pode excluir uma entidade usando suas chaves de partição e de linha. Neste exemplo, o objeto task1 contém os valores rowKey e partitionKey da entidade a ser excluída. Depois o objeto é passado para o método deleteEntity .
const tableClient = new TableClient(
tablesEndpoint,
tableName,
new AzureNamedKeyCredential("<accountName>", "<accountKey>")
);
await tableClient.deleteEntity("hometasks", "1");
// Entity deleted
Observação
Considere o uso de ETags ao excluir itens, para garantir que o item não seja modificado por outro processo. Veja Atualizar uma entidade para obter informações sobre o uso de ETags.
Excluir uma tabela
O código a seguir exclui uma tabela de uma conta de armazenamento.
await tableClient.deleteTable(mytable);
// Table deleted
Usar tokens de continuação
Quando você estiver consultando tabelas com grandes quantidades de resultados, deverá procurar tokens de continuação. Pode haver grandes quantidades de dados disponíveis para a sua consulta dos quais talvez você não saiba, se não criá-la de modo a reconhecer quando um token de continuação está presente.
O objeto results retornado durante a consulta de entidades define uma propriedade continuationToken
quando esse token está presente. Você pode usar isso ao realizar uma consulta para continuar a mover-se pela partição e entidades de tabela.
Ao consultar, é possível fornecer um parâmetro continuationToken
entre a instância do objeto de consulta e a função de retorno de chamada:
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 compartilhado
SAS (Assinaturas de acesso compartilhado) são uma maneira segura de fornecer acesso granular a tabelas sem fornecer o nome ou as chaves da conta de Armazenamento. As SAS são muitas vezes usadas para fornecer acesso limitado aos seus dados, como permitir que um aplicativo móvel consulte registros.
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 inicial e final durante as quais a SAS é válida, assim 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 proprietário da 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
});
O aplicativo cliente usa a SAS com AzureSASCredential para executar operações na tabela. O exemplo a seguir conecta à tabela e executa uma consulta. Confira o artigo Conceder acesso limitado a recursos de Armazenamento do Azure usando SAS (assinaturas de acesso compartilhado) sobre 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 só com acesso de consulta, se você tentar inserir, atualizar ou excluir entidades, surgirá um erro.
Listas de Controle de Acesso
Você também pode usar uma ACL (Lista de Controle de Acesso) para definir a política de acesso para uma SAS. Isso é útil se você quiser permitir que vários clientes acessem a tabela, mas oferecem diferentes políticas de acesso para cada cliente.
Uma ACL é implementada através de um conjunto de políticas de acesso, com uma ID associada a cada política. O seguinte exemplo 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. Essa abordagem permite:
tableClient.getAccessPolicy();
tableClient.setAccessPolicy(sharedAccessPolicy);
Após a definição da ACL, você pode criar uma SAS com base na ID de uma política. O exemplo a seguir cria uma nova SAS para 'user2':
tableSAS = generateTableSas("hometasks",cred,{identifier:'user2'});
Próximas etapas
Para obter mais informações, consulte os recursos a seguir.
- O Gerenciador de Armazenamento do Microsoft Azure é um aplicativo autônomo e gratuito da Microsoft que possibilita o trabalho visual com os dados do Armazenamento do Azure no Windows, MacOS e Linux.
- Repositório SDK do Armazenamento do Azure para Node.js no GitHub.
- Criar um aplicativo Web do Node.js no Azure
- Criar e implantar um aplicativo Node.js para um serviço de nuvem do AzureServiço de nuvem do Node.js (usando o Windows PowerShell)