Verwenden von Azure Table Storage oder Azure Cosmos DB for Table über Node.js

GILT FÜR: Tabelle

Tipp

Der Inhalt in diesem Artikel gilt für Azure Table Storage und Azure Cosmos DB for Table. Die API for Table ist ein Premiumangebot für Tabellenspeicher und bietet Tabellen mit optimiertem Durchsatz, globaler Verteilung und automatischen sekundären Indizes.

In diesem Artikel erfahren Sie, wie Sie Tabellen erstellen, Daten speichern und CRUD-Vorgänge für diese Daten ausführen. Die Beispiele sind in Node.js geschrieben.

Erstellen eines Azure-Dienstkontos

Sie können im Azure-Tabellenspeicher oder in Azure Cosmos DB mit Tabellen arbeiten. Weitere Informationen zu den Unterschieden zwischen Tabellenangeboten dieser beiden Dienste finden Sie in der Übersicht zur API für Table. Sie müssen ein Konto für den Dienst erstellen, den Sie verwenden werden. In den folgenden Abschnitten wird gezeigt, wie Sie sowohl den Azure-Tabellenspeicher als auch das Azure Cosmos DB-Konto erstellen können. Sie können jedoch auch nur eines von beiden verwenden.

Erstellen eines Azure-Speicherkontos

Ein Azure-Speicherkonto erstellen Sie am einfachsten im Azure-Portal. Weitere Informationen finden Sie unter Erstellen von Speicherkonten.

Sie können ein Azure-Speicherkonto auch mit Azure PowerShell oder mit der Azure CLI erstellen.

Wenn Sie zu diesem Zeitpunkt kein Speicherkonto erstellen möchten, können Sie auch den Azure-Speicheremulator zum Ausführen und Testen Ihres Codes in einer lokalen Umgebung verwenden. Weitere Informationen finden Sie unter Verwenden des Azure-Speicheremulators für Entwicklung und Tests.

Erstellen eines Kontos für Azure Cosmos DB for Table

Anweisungen zum Erstellen eines Kontos für Azure Cosmos DB for Table finden Sie unter Erstellen eines Datenbankkontos.

Konfigurieren Ihrer Anwendung für den Zugriff auf Table Storage

Um Azure Storage oder Azure Cosmos DB verwenden zu können, müssen Sie das Azure Tables SDK für Node.js herunterladen. Es enthält eine Reihe von Bibliotheken, die mit den REST-Speicherdiensten kommunizieren.

Verwenden des Node-Paket-Managers (NPM) zum Installieren des Pakets

  1. Verwenden Sie eine Befehlszeilenschnittstelle, z. B. PowerShell (Windows), Terminal (Mac) oder Bash (Unix), und navigieren Sie zum Ordner, in dem Sie die Beispielanwendung erstellt haben.
  2. Geben Sie Folgendes im Befehlsfenster:
   npm install @azure/data-tables
  1. Sie können den Befehl ls manuell ausführen, um zu überprüfen, ob der Ordner node_modules erstellt wurde. In diesem Ordner finden Sie das Paket @azure/data-tables mit den Bibliotheken, die Sie benötigen, um auf Tabellen zuzugreifen.

Importieren des Pakets

Fügen Sie den folgenden Code am Anfang der Datei server.js in der Anwendung hinzu:

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

Herstellen der Verbindung mit dem Azure-Tabellenspeicherdienst

Sie können entweder eine Verbindung mit dem Azure Storage-Konto oder dem Konto für Azure Cosmos DB for Table herstellen. Rufen Sie den gemeinsam verwendeten Schlüssel oder die Verbindungszeichenfolge basierend auf dem jeweils verwendeten Kontotyp ab.

Erstellen des Tabellendienstclients auf der Grundlage eines gemeinsam verwendeten Schlüssels

Das Azure-Modul liest die Umgebungsvariablen AZURE_ACCOUNT, AZURE_ACCESS_KEY und AZURE_TABLES_ENDPOINT, um Informationen zu erhalten, die für die Verbindung mit Ihrem Azure Storage-Konto oder mit Azure Cosmos DB erforderlich sind. Wenn diese Umgebungsvariablen nicht festgelegt wurden, müssen die Kontoinformationen beim Aufruf von TableServiceClient angegeben werden. Der folgende Code erstellt beispielsweise ein TableServiceClient-Objekt:

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

const tableService = new TableServiceClient(
  endpoint,
  credential
);

Erstellen des Tabellendienstclients auf der Grundlage einer Verbindungszeichenfolge

Um eine Verbindung mit Azure Cosmos DB oder dem Storage-Konto hinzuzufügen, erstellen Sie ein TableServiceClient-Objekt, und geben Sie Ihren Kontonamen, den Primärschlüssel und den Endpunkt an. Sie können diese Werte im Azure-Portal für Ihr Azure Cosmos DB- oder Storage-Konto unter Einstellungen>Verbindungszeichenfolge kopieren. Beispiel:

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

Erstellen einer Tabelle

Wenn Sie createTable aufrufen, wird eine neue Tabelle mit dem angegebenen Namen erstellt, sofern sie nicht bereits vorhanden ist. Im folgenden Beispiel wird eine neue Tabelle namens 'mytable' erstellt, wenn diese noch nicht vorhanden ist:

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

Erstellen des Table-Clients

Um mit einer Tabelle zu interagieren, sollten Sie ein TableClient-Objekt mit den gleichen Anmeldeinformationen erstellen, die Sie zum Erstellen von TableServiceClientverwendet haben. TableClient erfordert auch den Namen der Zieltabelle.

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

Hinzufügen einer Entität zu einer Tabelle

Um eine Entität hinzuzufügen, erstellen Sie zunächst ein Objekt, das die Entitätseigenschaften definiert. Alle Entitäten müssen partitionKey und rowKey enthalten, die eindeutige Bezeichner für die Entität sind.

  • partitionKey: Bestimmt die Partition, in der die Entität gespeichert wird.
  • rowKey: Identifiziert die Entität innerhalb der Partition eindeutig.

PartitionKey und RowKey müssen Zeichenfolgenwerte sein.

Nachfolgend sehen Sie ein Beispiel für die Definition einer Entität. dueDate ist als Typ Date definiert. Die Angabe des Typs ist optional. Nicht angegebene Typen werden abgeleitet.

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

Hinweis

Für jeden Datensatz gibt es auch ein Timestamp-Feld, das von Azure festgelegt wird, wenn eine Entität eingefügt oder aktualisiert wird.

Um eine Entität der Tabelle hinzuzufügen, übergeben Sie das Entitätsobjekt der createEntity-Methode.

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

Wenn der Vorgang erfolgreich ist, enthält result das ETag und Informationen zum Vorgang.

Beispielantwort:

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

Aktualisieren einer Entität

Die verschiedenen Modi für updateEntity- und upsertEntity-Methoden

  • Mergen: Aktualisiert eine Entität, indem die Eigenschaften der Entität aktualisiert werden, ohne die vorhandene Entität zu ersetzen.
  • Ersetzen: Aktualisiert eine vorhandene Entität, indem die gesamte Entität ersetzt wird.

Das folgende Beispiel zeigt, wie eine Entität mit upsertEntity aktualisiert wird:

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

Die Aktualisierung schlägt fehl, wenn die Entität, die aktualisiert werden soll, nicht vorhanden ist. Wenn Sie eine Entität unabhängig davon, ob sie bereits vorhanden ist, speichern möchten, verwenden Sie daher upsertEntity.

Bei erfolgreichen Aktualisierungsvorgängen enthält das result das ETag der aktualisierten Entität.

Arbeiten mit Gruppen von Entitäten

Gelegentlich ist es sinnvoll, mehrere Vorgänge zusammen in einem Batch zu senden, um die atomische Verarbeitung durch den Server sicherzustellen. Erstellen Sie hierzu ein Array von Vorgängen, und übergeben Sie es an die submitTransaction-Methode für TableClient.

Im folgenden Beispiel wird gezeigt, wie zwei Entitäten in einem Stapel übermittelt werden:

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

Bei erfolgreichen Batchvorgängen enthält result Informationen für jeden Vorgang im Batch.

Abrufen einer Entität nach Schlüssel

Wenn Sie eine bestimmte Entität basierend auf PartitionKey und RowKey zurückgeben möchten, verwenden Sie die getEntity-Methode.

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

Nach Abschluss des Vorgangs enthält result die Entität.

Abfragen einer Gruppe von Entitäten

Im folgenden Beispiel wird eine Abfrage erstellt, die die ersten fünf Elemente mit dem PartitionKey „hometasks“ zurückgibt und alle Entitäten in der Tabelle auflistet.

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

Abfragen einer Teilmenge von Entitätseigenschaften

Mit einer Abfrage einer Tabelle können nur einige wenige Felder einer Entität aufgerufen werden. Somit wird die Bandbreite reduziert und die Abfrageleistung gesteigert, vor allem bei großen Entitäten. Verwenden Sie die select -Klausel, und übergeben Sie die Namen der zurückzugebenden Felder. Die folgende Abfrage gibt beispielsweise nur die Felder description und dueDate zurück.

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

Löschen einer Entität

Sie können eine Entität unter Verwendung ihres Partitions- und Zeilenschlüssels löschen. In diesem Beispiel enthält das Objekt task1 die rowKey- und partitionKey-Werte der zu löschenden Entität. Dann wird das Objekt der deleteEntity -Methode übergeben.

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

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

Hinweis

Es ist ratsam, beim Löschen von Elementen ETags zu verwenden, um sicherzustellen, dass das Element nicht von einem anderen Prozess geändert wurde. Informationen zum Verwenden von ETags finden Sie unter Aktualisieren einer Entität .

Löschen einer Tabelle

Mit dem folgenden Code wird eine Tabelle aus einem Speicherkonto gelöscht.

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

Verwenden von Fortsetzungstoken

Wenn Sie in Tabellen umfangreiche Ergebnismengen abfragen, sollten Sie nach Fortsetzungstoken suchen. Möglicherweise sind umfangreiche Datenmengen für die Abfrage verfügbar, die Sie nicht erkennen können, wenn ein Fortsetzungstoken vorhanden ist.

Das beim Abfragen von Entitäten zurückgegebene results-Objekt legt eine continuationToken-Eigenschaft fest, wenn ein derartiges Token vorhanden ist. Diese können Sie dann beim Durchführen einer Abfrage verwenden, um die Partitions- und Tabellenentitäten zu durchlaufen.

Bei der Abfrage können Sie ein continuationToken-Parameter zwischen der query-Objektinstanz und der callback-Funktion bereitstellen:

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

Arbeiten mit Shared Access Signatures

Shared Access Signatures (SAS) ermöglichen auf sichere Art und Weise differenzierten Zugriff auf Tabellen, ohne Speicherkontonamen oder -schlüssel anzugeben. SAS werden häufig verwendet, um eingeschränkten Zugriff auf Ihre Daten zu bieten, beispielsweise um einer mobilen App die Abfrage von Datensätzen zu ermöglichen.

Eine vertrauenswürdige Anwendung, z. B. ein cloudbasierter Dienst, generiert mit der generateTableSas-Methode des TableClient-Objekts eine SAS und stellt sie für eine nicht vertrauenswürdige oder teilweise vertrauenswürdige Anwendung bereit, z. B. für eine mobile App. Die SAS wird mithilfe einer Richtlinie generiert, die das Anfangs- und das Enddatum der Gültigkeit der SAS sowie die Zugriffsstufe definiert, die dem Inhaber der SAS gewährt wird.

Im folgenden Beispiel wird eine neue SAS-Richtlinie generiert, die es dem SAS-Besitzer ermöglicht, die Tabelle abzufragen („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
});

Die Clientanwendung verwendet die SAS dann zusammen mit AzureSASCredential, um Vorgänge für die Tabelle auszuführen. Im folgenden Beispiel wird eine Verbindung mit der Tabelle hergestellt und eine Abfrage ausgeführt. Im Artikel Gewähren von eingeschränktem Zugriff auf Azure Storage-Ressourcen mithilfe von SAS (Shared Access Signature) können Sie sich das Format von tableSAS ansehen.

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

Da die SAS nur mit Abfragezugriff generiert wurde, wird ein Fehler zurückgegeben, wenn Sie versuchen, Entitäten einzufügen, zu aktualisieren oder zu löschen.

Zugriffssteuerungslisten

Sie können auch eine Zugriffssteuerungsliste (Access Control List, ACL) verwenden, um die Zugriffsrichtlinie für eine SAS festzulegen. Dies ist nützlich, wenn Sie mehreren Clients Zugriff auf die Tabelle gewähren, aber für jeden Client andere Zugriffsrichtlinien angeben möchten.

Eine ACL wird in einem Array von Zugriffsrichtlinien implementiert, wobei jeder Richtlinie eine ID zugeordnet wird. Im folgenden Beispiel werden zwei Richtlinien definiert, eine für "user1" und eine für "user2":

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

Im folgenden Beispiel wird zunächst die aktuelle ACL für die Tabelle hometasks abgerufen. Anschließend werden die neuen Richtlinien mit setAccessPolicy hinzugefügt. Dieser Ansatz ermöglicht Folgendes:

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

Nachdem die ACL festgelegt wurde, können Sie basierend auf der ID für eine Richtlinie eine SAS erstellen. Im folgenden Beispiel wird eine neue SAS für 'user2' erstellt:

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

Nächste Schritte

Weitere Informationen finden Sie in den folgenden Ressourcen.