Jak używać usługi Azure Table Storage lub usługi Azure Cosmos DB dla tabel z Node.js

DOTYCZY: Tabeli

Napiwek

Zawartość tego artykułu dotyczy usług Azure Table Storage i Azure Cosmos DB for Table. Interfejs API dla tabel to oferta premium dla magazynu tabel, która oferuje tabele zoptymalizowane pod kątem przepływności, dystrybucję globalną i automatyczne indeksy pomocnicze.

W tym artykule pokazano, jak tworzyć tabele, przechowywać dane i wykonywać operacje CRUD na tych danych. Przykłady są zapisywane w Node.js.

Tworzenie konta usługi Azure

Możesz pracować z tabelami przy użyciu usługi Azure Table Storage lub usługi Azure Cosmos DB. Aby dowiedzieć się więcej o różnicach między ofertami tabel w tych dwóch usługach, zobacz omówienie interfejsu API dla tabel. Aby móc korzystać z wybranej usługi, musisz w niej utworzyć konto. W poniższych sekcjach pokazano, jak utworzyć zarówno usługę Azure Table Storage, jak i konto usługi Azure Cosmos DB, jednak możesz po prostu użyć jednego z nich.

Tworzenie konta usługi Azure Storage

Najprostszym sposobem utworzenia konta usługi Azure Storage jest użycie witryny Azure Portal. Więcej informacji można znaleźć w temacie Tworzenie konta magazynu.

Możesz utworzyć konto usługi Azure Storage przy użyciu programu Azure PowerShell lub interfejsu wiersza polecenia platformy Azure.

Jeśli w tej chwili nie chcesz tworzyć konta magazynu, możesz również użyć emulatora usługi Azure Storage do uruchomienia i przetestowania kodu w środowisku lokalnym. Aby uzyskać więcej informacji, zobacz Use the Azure Storage Emulator for development and testing (Używanie emulatora usługi Azure Storage do programowania i testowania).

Tworzenie konta usługi Azure Cosmos DB dla tabel

Aby uzyskać instrukcje dotyczące tworzenia konta usługi Azure Cosmos DB dla tabel, zobacz Tworzenie konta bazy danych.

Konfigurowanie aplikacji w celu uzyskania dostępu do usługi Table Storage

Aby korzystać z usługi Azure Storage lub Azure Cosmos DB, potrzebujesz zestawu SDK tabel platformy Azure dla Node.js, który zawiera zestaw bibliotek wygody komunikujących się z usługami REST usługi Storage.

Instalowanie menedżera NPM (Node Package Manager)

  1. Użyj interfejsu wiersza polecenia, takiego jak PowerShell (Windows), Terminal (Mac) lub Bash (Unix), i przejdź do folderu, w którym utworzono aplikację.
  2. Wpisz następujące polecenie w oknie polecenia:
   npm install @azure/data-tables
  1. Możesz ręcznie uruchomić polecenie ls, aby sprawdzić, czy utworzono folder node_modules. W tym folderze znajduje się pakiet @azure/data-tables zawierający biblioteki potrzebne do uzyskiwania dostępu do tabel.

Importowanie pakietu

Dodaj następujący kod na początku pliku server.js w aplikacji:

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

Łączenie się z usługą Azure Table Storage

Możesz nawiązać połączenie z kontem usługi Azure Storage lub kontem usługi Azure Cosmos DB dla tabeli. Pobierz klucz wspólny lub parametry połączenia na podstawie typu używanego konta.

Tworzenie klienta usługi Table Service na podstawie klucza współużytkowanego

Moduł platformy Azure odczytuje zmienne środowiskowe AZURE_ACCOUNT i AZURE_ACCESS_KEY oraz AZURE_TABLES_ENDPOINT, aby uzyskać informacje wymagane do nawiązania połączenia z kontem usługi Azure Storage lub usługą Azure Cosmos DB. Jeśli te zmienne środowiskowe nie są ustawione, należy określić informacje o koncie podczas wywoływania metody TableServiceClient. Na przykład poniższy kod tworzy TableServiceClient obiekt:

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

const tableService = new TableServiceClient(
  endpoint,
  credential
);

Tworzenie klienta usługi Table Service na podstawie parametry połączenia

Aby dodać połączenie z usługą Azure Cosmos DB lub kontem magazynu, utwórz TableServiceClient obiekt i określ nazwę konta, klucz podstawowy i punkt końcowy. Te wartości można skopiować z Ustawienia> Połączenie ion String w witrynie Azure Portal dla konta usługi Azure Cosmos DB lub konta magazynu. Na przykład:

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

Utwórz tabelę

Wywołanie metody w celu createTable utworzenia nowej tabeli o określonej nazwie, jeśli jeszcze nie istnieje. W poniższym przykładzie jest tworzona nowa tabela o nazwie „mytable”, jeśli jeszcze nie istnieje:

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

Tworzenie klienta tabel

Aby wchodzić w interakcje z tabelą TableClient , należy utworzyć obiekt przy użyciu tych samych poświadczeń użytych do utworzenia obiektu TableServiceClient. Element TableClient wymaga również nazwy tabeli docelowej.

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

Dodawanie jednostki do tabeli

Aby dodać jednostkę, najpierw utwórz obiekt, który definiuje właściwości jednostki. Wszystkie jednostki muszą zawierać wartości partitionKey i rowKey, które są unikatowymi identyfikatorami jednostki.

  • partitionKey — określa partycję, w której jest przechowywana jednostka.
  • rowKey — unikatowo identyfikuje jednostkę w ramach partycji.

Zarówno partitionKey, jak i rowKey muszą być wartościami ciągów.

Poniżej znajduje się przykład definiowania jednostki. Data ukończenia jest definiowana jako typ Date. Określenie typu jest opcjonalne — w przypadku rezygnacji typy zostaną wywnioskowane.

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

Uwaga

Istnieje również pole dla każdego rekordu, które jest ustawiane przez platformę Timestamp Azure po wstawieniu lub zaktualizowaniu jednostki.

Aby dodać jednostkę do tabeli, przekaż obiekt jednostki do createEntity metody .

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

Jeśli operacja zakończy się pomyślnie, result zawiera element ETag i informacje o operacji.

Przykładowa odpowiedź:

{ 
  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'
}

Aktualizowanie jednostki

Różne tryby dla updateEntity metod i upsertEntity

  • Scalanie: Aktualizacje jednostkę, aktualizując właściwości jednostki bez zastępowania istniejącej jednostki.
  • Zastąp: Aktualizacje istniejącą jednostkę, zastępując całą jednostkę.

W poniższym przykładzie pokazano aktualizowanie jednostki przy użyciu polecenia upsertEntity:

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

Jeśli aktualizowana jednostka nie istnieje, operacja aktualizacji zakończy się niepowodzeniem; Dlatego jeśli chcesz przechowywać jednostkę niezależnie od tego, czy już istnieje, użyj polecenia upsertEntity.

Element result pomyślnie zakończonych operacji aktualizowania zawiera tag Etag zaktualizowanej jednostki.

Praca z grupami jednostek

Czasami warto przesłać jednocześnie wiele operacji w partii, aby zapewnić niepodzielne przetwarzanie przez serwer. Aby to osiągnąć, utwórz tablicę operacji i przekaż ją do submitTransaction metody w pliku TableClient.

W poniższym przykładzie przedstawiono przesyłanie dwóch jednostek w partii:

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

W przypadku operacji wsadowych zakończonych pomyślnie element result zawiera informacje dotyczące każdej operacji w partii.

Pobieranie jednostek według klucza

Aby zwrócić określoną jednostkę na podstawie wartości PartitionKey i RowKey, użyj metody getEntity .

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

Po ukończeniu tej operacji element result zawiera jednostkę.

Wykonywanie zapytania względem zestawu jednostek

Poniższy przykład tworzy zapytanie, które zwraca pięć pierwszych elementów z kluczem PartitionKey "hometasks" i wyświetla listę wszystkich jednostek w tabeli.

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);
}

Tworzenie zapytania do podzbioru właściwości jednostki

Za pomocą zapytania wykonywanego względem tabeli można pobrać tylko kilka pól z jednostki. Redukuje to przepustowość i może poprawiać wydajność zapytań, zwłaszcza w przypadku dużych jednostek. Użyj klauzuli select i przekaż nazwy pól do zwrócenia. Na przykład poniższe zapytanie zwraca tylko wartości pól description i 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;
}

Usuwanie encji

Jednostkę można usunąć za pomocą kluczy partycji i wierszy. W tym przykładzie obiekt task1 zawiera wartości rowKey i partitionKey jednostki do usunięcia. Następnie obiekt jest przekazywany do metody deleteEntity.

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

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

Uwaga

Rozważ użycie tagów ETag podczas usuwania elementów, aby upewnić się, że element nie został zmodyfikowany przez inny proces. Aby uzyskać informacje na temat używania tagów Etag, zobacz Aktualizowanie jednostki.

Usuń tabelę

Poniższy kod usuwa tabelę z konta magazynu.

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

Korzystanie z tokenów kontynuacji

W przypadku wykonywania zapytań dotyczących tabel z dużą liczbą wyników należy poszukać tokenów kontynuacji. Mogą istnieć duże ilości danych dostępnych dla zapytania, o których możesz nie wiedzieć, jeśli nie skompilujesz rozpoznawania obecności tokenu kontynuacji.

Obiekt results zwracany w przypadku wykonywania zapytań dotyczących jednostek ustawia właściwość continuationToken, gdy taki token istnieje. Możesz go następnie użyć podczas wykonywania zapytania, aby kontynuować poruszanie się w obrębie jednostek tabeli i partycji.

Podczas wykonywania zapytania możesz określić parametr continuationToken między wystąpieniem obiektu zapytania i funkcją wywołania zwrotnego:

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);
   }
 }

Praca z sygnaturami dostępu współdzielonego

Sygnatury dostępu współdzielonego (SAS) to bezpieczny sposób zapewnienia szczegółowego dostępu do tabel bez podawania kluczy ani nazwy konta usługi Storage. Sygnatury dostępu współdzielonego są często używane do udzielania ograniczonych praw dostępu do danych, takich jak zezwalanie aplikacji mobilnej na wykonywanie zapytań dotyczących rekordów.

Zaufana aplikacja, taka jak usługa w chmurze, generuje sygnaturę dostępu współdzielonego przy użyciu metody generateTableSas obiektu TableClient i udostępnia ją niezaufanej lub częściowo zaufanej aplikacji, takiej jak aplikacja mobilna. Sygnatura dostępu współdzielonego jest generowana przy użyciu zasad opisujących daty rozpoczęcia i zakończenia okresu, w którym ta sygnatura obowiązuje, a także poziom dostępu przyznany właścicielowi sygnatury dostępu współdzielonego.

Poniższy przykład generuje nowe zasady dostępu współdzielonego, które umożliwią właścicielowi sygnatury dostępu współdzielonego wykonywanie zapytań względem tabeli ('r').

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
});

Następnie aplikacja kliencka używa sygnatury dostępu współdzielonego z usługą AzureSASCredential do wykonywania operacji względem tabeli. W poniższym przykładzie następuje połączenie z tabelą i wykonanie zapytania. Zobacz Artykuł Udzielanie ograniczonego dostępu do zasobów usługi Azure Storage przy użyciu sygnatur dostępu współdzielonego (SAS), aby zapoznać się z formatem 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}` }
});

Ponieważ sygnatura dostępu współdzielonego została wygenerowana z dostępem tylko do zapytania, próba wstawienia, zaktualizowania lub usunięcia jednostek spowoduje zwrócenie błędu.

Listy kontroli dostępu

Do ustawienia zasad dostępu powiązanych z sygnaturą dostępu współdzielonego można również użyć listy kontroli dostępu (ACL, Access Control List). Jest to przydatne, jeśli chcesz umożliwić wielu klientom dostęp do tabeli, ale uwzględnia różne zasady dostępu dla poszczególnych klientów.

Lista ACL jest implementowana przy użyciu tablicy zasad dostępu z identyfikatorem skojarzonym z poszczególnymi zasadami. W poniższym przykładzie zdefiniowano dwie zasady, odpowiednio dla użytkowników „user1” i „user2”:

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

Poniższy przykład pobiera bieżącą listę ACL dla tabeli hometasks , a następnie dodaje nowe zasady przy użyciu funkcji setAccessPolicy. W przypadku takiego podejścia:

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

Po ustawieniu listy ACL można następnie utworzyć sygnaturę dostępu współdzielonego na podstawie identyfikatora zasad. W poniższym przykładzie jest tworzona nowa sygnatura dostępu współdzielonego dla użytkownika „user2”:

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

Następne kroki

Więcej informacji zawierają poniższe zasoby.