共用方式為


如何從 Node.js 使用 Azure 表格儲存體 或Azure Cosmos DB for Table

適用於: 桌子

提示

本文中的內容適用於 Azure 資料表儲存體和 Azure Cosmos DB for Table。 API for Table 是資料表儲存體的進階供應項目,可提供輸送量最佳化的資料表、全域散發,以及自動次要索引。

此文章說明如何建立資料表、儲存您的資料,以及對上述資料執行 CRUD 作業。 範例是以 Node.js 撰寫的。

建立 Azure 服務帳戶

您可以使用 Azure 表格儲存體或 Azure Cosmos DB 來搭配使用表格。 若要深入瞭解這兩個服務中的資料表供應項目間的差異,請參閱 API for Table 概觀。 您必須為您要使用的服務建立帳戶。 下列各節說明如何建立 Azure 資料表儲存體和 Azure Cosmos DB 帳戶,不過您可以只使用其中一個。

建立 Azure 儲存體帳戶

建立 Azure 儲存體帳戶最簡單的方法,就是使用 Azure 入口網站。 若要深入了解,請參閱 建立儲存體帳戶

您也可以使用 Azure PowerShellAzure CLI 來建立 Azure 儲存體帳戶。

如果您不想在此時建立儲存體帳戶,也可以使用 Azure 儲存體模擬器在本機環境中執行並測試您的程式碼。 如需詳細資訊,請參閱使用 Azure 儲存體模擬器進行開發和測試

建立 Azure Cosmos DB for Table 帳戶

如需建立 Azure Cosmos DB for Table 帳戶的相關指示,請參閱建立資料庫帳戶

設定您的應用程式來存取資料表儲存體

若要使用 Azure 儲存體或 Azure Cosmos DB,您需要適用於 Node.js 的 Azure 資料表 SDK,這包含一組能與「儲存體 REST」服務進行通訊的便利程式庫。

使用 Node Package Manager (NPM) 安裝封裝

  1. 使用命令列介面,例如 PowerShell (Windows)、終端機 (Mac) 或 Bash (Unix),瀏覽至儲存所建立應用程式的資料夾。
  2. 在命令視窗中輸入下列命令:
   npm install @azure/data-tables
  1. 您可以手動執行 ls 命令,確認已建立 node_modules 資料夾。 您可以在該資料夾中找到 @azure/data-tables 套件,當中包含存取資料表所需的程式庫。

匯入封裝

將下列程式碼加在應用程式中的 server.js 檔案之上:

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

連線到 Azure 表格服務

您可以連線到 Azure 儲存體帳戶或 Azure Cosmos DB for Table 帳戶。 根據您使用的帳戶類型,取得共用金鑰或連接字串。

藉由共用金鑰建立資料表服務用戶端

Azure 模組會讀取環境變數 AZURE_ACCOUNT、AZURE_ACCESS_KEY 和 AZURE_TABLES_ENDPOINT 以取得連線至 Azure 儲存體帳戶或 Azure Cosmos DB 所需的資訊。 如果未設定這些環境變數,則呼叫 TableServiceClient 時必須指定帳戶資訊。 例如,下列程式碼會建立 TableServiceClient 物件:

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

const tableService = new TableServiceClient(
  endpoint,
  credential
);

藉由連接字串建立資料表服務用戶端

若要新增 Azure Cosmos DB 或儲存體帳戶連線,請建立 TableServiceClient 物件,然後指定您的帳戶名稱、主要索引鍵及端點。 您可以在 Azure 入口網站中,從 Azure Cosmos DB 帳戶或儲存體帳戶的 [設定]> [連接字串] 中複製這些值。 例如:

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

建立表格

呼叫 createTable 時,會以指定的名稱建立新的資料表 (若此資料表尚未存在)。 如果名為 'mytable' 的資料表尚不存在,下列範例便會建立這個新資料表:

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

建立資料表用戶端

若要與資料表互動,您應使用先前用來建立 TableServiceClient 的相同認證來建立 TableClient 物件。 TableClient 也需要目標資料表的名稱。

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

將實體新增至資料表

若要新增實體,請先建立一個定義實體屬性的物件。 所有實體必須包含 partitionKeyrowKey,這些是實體的唯一識別碼。

  • partitionKey - 可決定儲存實體的分割區。
  • rowKey - 可在分割區內唯一地識別實體。

partitionKey and rowKey 都必須是字串值。

以下是定義實體的範例。 dueDate 定義為 Date 的類型。 您可以視需要指定類型,若未指定,系統就會推斷類型。

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

注意

每筆記錄還有 Timestamp 欄位,插入或更新實體時,Azure 會設定此欄位。

若要將實體新增至資料表,請將實體物件傳給 createEntity 方法。

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

如果作業成功,則 result 會包含 ETag 和作業的相關資訊。

範例回應:

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

更新實體

updateEntityupsertEntity 方法的不同模式

  • 合併:藉由更新實體的屬性來更新實體,而不需要取代現有的實體。
  • 取代:藉由取代整個實體來更新現有實體。

下列範例示範使用 upsertEntity 來更新實體:

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

如果所要更新的實體不存在,更新作業就會失敗;因此,如果您想要儲存該實體,而不論實體是否已經存在,請使用 upsertEntity

成功的更新作業 result 會包含所更新實體的 Etag

使用實體群組

有時候批次提交多個操作是有意義的,可以確保伺服器會進行不可部分完成的處理。 若要完成這項作業,請建立作業的陣列,並將其傳遞至 TableClient 上的 submitTransaction 方法。

下列範例示範在批次中提交兩個實體:

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

就成功的批次作業而言,result 會包含批次中每個作業的相關資訊。

依索引鍵擷取實體

若要根據 PartitionKeyRowKey 傳回特定的實體,請使用 getEntity 方法。

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

在此作業完成之後,result 就會包含實體。

查詢實體集合

下列範例建立的查詢會傳回 PartitionKey 為「hometasks」的前五個項目,並列出資料表中的所有實體。

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

查詢實體屬性的子集

一項資料表查詢可以只擷取實體的少數欄位。 這可以減少頻寬並提高查詢效能 (尤其是對大型實體而言)。 請使用 select 子句,並傳遞要傳回的欄位名稱。 例如,下列查詢只會傳回 descriptiondueDate 欄位。

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

刪除實體

您可以使用實體的資料分割和資料列索引鍵來刪除實體。 在此範例中,task1 物件包含要刪除之實體的 rowKeypartitionKey 值。 然後物件會傳給 deleteEntity 方法。

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

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

注意

刪除項目時應該考慮使用 ETag,以確保項目未被另一個程序修改過。 請參閱 更新實體 ,以取得使用 ETag 的相關資訊。

刪除資料表

下列程式碼會從儲存體帳戶刪除資料表。

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

使用接續 Token

當您查詢大量結果的資料表時,請尋找接續 Token。 因為您的查詢可能會產生大量可用的資料,如果該查詢並非可識別接續權杖存在的查詢,可能會無法得知。

當此類權杖存在時,在查詢實體期間傳回的 results 物件便會設定 continuationToken 屬性。 您可以在執行查詢使用此方法以繼續在分割和資料表實體之間移動。

查詢時,您可以在查詢物件執行個體與回呼函式之間提供一個 continuationToken 參數:

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

使用共用存取簽章

共用存取簽章 (SAS) 可安全地提供對資料表的細微存取權,而不必提供您的儲存體帳戶名稱或金鑰。 SAS 通常用來提供對資料的有限存取,例如允許行動應用程式查詢記錄。

信任的應用程式 (例如雲端型服務) 會使用 TableClientgenerateTableSas 來產生 SAS,並將其提供給不信任或不完全信任的應用程式 (例如行動應用程式)。 SAS 是使用原則來產生,該原則描述 SAS 有效期間的開始和結束日期,以及授與 SAS 持有者的存取等級。

下列範例會產生新的共用存取原則,讓 SAS 持有者可以查詢 (「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
});

用戶端應用程式接著以 AzureSASCredential 來使用 SAS,對資料表執行作業。 下列範例會連線到資料表並執行查詢。 如需關於資料表 SAS 的格式詳細資訊,請參閱使用共用存取簽章 (SAS) 對 Azure 儲存體資源授與有限存取權一文。

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

由於產生的 SAS 只具有查詢權限,因此如果您嘗試插入、更新或刪除實體,就會傳回錯誤。

存取控制清單

您也可以使用存取控制清單 (ACL) 來設定 SAS 的存取原則。 如果您想要允許多個用戶端存取資料表,但對每個用戶端提供不同的存取原則,這便相當有用。

ACL 是使用存取原則陣列來實作,每個原則有相關聯的識別碼。 下列範例定義兩個原則,其中一個用於 'user1',另一個用於 'user2':

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

下列範例會取得 hometasks 資料表的目前 ACL,然後使用 setAccessPolicy 來新增原則。 此方法允許:

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

設定 ACL 之後,您便可以根據原則的識別碼來建立 SAS。 下列範例會建立 'user2' 的新 SAS:

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

下一步

如需詳細資訊,請參閱下列資源。