Node.js hello world

這個程式碼範例是在 Node.js 上執行的「hello world」應用程式,示範如何完成下列工作:

  • 設定驗證方法
  • 連線至 Bigtable 執行個體。
  • 建立新的資料表。
  • 將資料寫入資料表。
  • 讀取資料。
  • 刪除資料表。

設定驗證方法

如要在本機開發環境中使用本頁的 Node.js 範例,請安裝並初始化 gcloud CLI,然後使用您的使用者憑證設定應用程式預設憑證。

  1. 安裝 Google Cloud CLI。

  2. 設定 gcloud CLI,使用您的聯合身分。

    詳情請參閱「使用聯合身分登入 gcloud CLI」。

  3. 為使用者帳戶建立本機驗證憑證:

    gcloud auth application-default login

    如果系統傳回驗證錯誤,且您使用外部識別資訊提供者 (IdP),請確認您已 使用聯合身分登入 gcloud CLI

詳情請參閱 這篇文章,瞭解如何設定本機開發環境的驗證機制。

執行範例

本程式碼範例使用 Node.js 適用的 Google Cloud 用戶端程式庫Bigtable 套件,與 Bigtable 進行通訊。

如要執行這個範例程式,請依照 GitHub 網頁上的說明操作。

搭配 Cloud 用戶端程式庫使用 Bigtable

這個應用程式範例會連線至 Bigtable,示範部分簡易作業。

須使用用戶端程式庫

@google-cloud/bigtable 模組。@google-cloud/bigtableBigtable

const {Bigtable} = require('@google-cloud/bigtable');

連線至 Bigtable

如要連結 Bigtable,請先建立新的 Bigtable 物件。然後呼叫其 instance() 方法,取得代表 Bigtable 執行個體的 Instance 物件。

const bigtableClient = new Bigtable();
const instance = bigtableClient.instance(INSTANCE_ID);
const table = instance.table(TABLE_ID);

建立資料表

呼叫例項的 table() 方法,取得代表「hello world」問候語資料表的 Table 物件。如果該資料表不存在,請呼叫資料表的 create() 方法,藉此建立含有一個資料欄系列的資料表,系統會在該資料欄系列中為每個資料值保留一個版本。

const {BigtableTableAdminClient} = require('@google-cloud/bigtable').v2;
const adminClient = new BigtableTableAdminClient();
const projectId = await adminClient.getProjectId();

let tableExists = true;
try {
  await adminClient.getTable({
    name: `projects/${projectId}/instances/${INSTANCE_ID}/tables/${TABLE_ID}`,
  });
} catch (e) {
  if (e.code === 5) {
    tableExists = false;
  }
}
if (!tableExists) {
  console.log(`Creating table ${TABLE_ID}`);
  const {BigtableTableAdminClient} = require('@google-cloud/bigtable').v2;
  const adminClient = new BigtableTableAdminClient();
  const projectId = await adminClient.getProjectId();
  await adminClient.createTable({
    parent: `projects/${projectId}/instances/${INSTANCE_ID}`,
    tableId: TABLE_ID,
    table: {
      columnFamilies: {
        [COLUMN_FAMILY_ID]: {
          gcRule: {
            maxNumVersions: 1,
          },
        },
      },
    },
  });
}

將資料列寫入資料表

使用問候語字串陣列為資料表建立幾個新的資料列:請呼叫陣列的 map() 方法,藉此建立代表資料列的新物件陣列。接著,呼叫資料表的 insert() 方法即可將資料列新增到資料表。

console.log('Write some greetings to the table');
const greetings = ['Hello World!', 'Hello Bigtable!', 'Hello Node!'];
const rowsToInsert = greetings.map((greeting, index) => ({
  // Note: This example uses sequential numeric IDs for simplicity, but this
  // pattern can result in poor performance in a production application.
  // Rows are stored in sorted order by key, so sequential keys can result
  // in poor distribution of operations across nodes.
  //
  // For more information about how to design an effective schema for Cloud
  // Bigtable, see the documentation:
  // https://cloud.google.com/bigtable/docs/schema-design
  key: `greeting${index}`,
  data: {
    [COLUMN_FAMILY_ID]: {
      [COLUMN_QUALIFIER]: {
        // Setting the timestamp allows the client to perform retries. If
        // server-side time is used, retries may cause multiple cells to
        // be generated.
        timestamp: new Date(),
        value: greeting,
      },
    },
  },
}));
await table.insert(rowsToInsert);

建立篩選器

讀取已寫入的資料前,請先建立篩選器,藉此限制 Bigtable 傳回的資料。即使資料欄含有較舊的儲存格,篩選器仍能指示 Bigtable 僅傳回每個資料欄的最新儲存格。

const filter = [
  {
    column: {
      cellLimit: 1, // Only retrieve the most recent version of the cell.
    },
  },
];

依資料列索引鍵讀取資料列

請呼叫資料表的 row() 方法,透過特定資料列索引鍵取得資料列的參考資料。接著,呼叫資料列的 get() 方法並傳入篩選器,即可取得該資料列中每個資料值的一個版本。

console.log('Reading a single row by row key');
const [singleRow] = await table.row('greeting0').get({filter});
console.log(`\tRead: ${getRowGreeting(singleRow)}`);

掃描所有資料表資料列

呼叫資料表的 getRows() 方法並傳入篩選器,即可取得資料表中的所有資料列。您已傳入篩選器,因此 Bigtable 只會傳回每個值的一個版本。

console.log('Reading the entire table');
// Note: For improved performance in production applications, call
// `Table#readStream` to get a stream of rows. See the API documentation:
// https://cloud.google.com/nodejs/docs/reference/bigtable/latest/Table#createReadStream
const [allRows] = await table.getRows({filter});
for (const row of allRows) {
  console.log(`\tRead: ${getRowGreeting(row)}`);
}

刪除資料表

運用資料表的 delete() 方法來刪除資料表。

console.log('Delete the table');
const request = {
  name: `projects/${projectId}/instances/${INSTANCE_ID}/tables/${TABLE_ID}`,
};
await adminClient.deleteTable(request);

全面整合使用

以下是不含評論的完整程式碼範例。




const {Bigtable} = require('@google-cloud/bigtable');

const TABLE_ID = 'Hello-Bigtable';
const COLUMN_FAMILY_ID = 'cf1';
const COLUMN_QUALIFIER = 'greeting';
const INSTANCE_ID = process.env.INSTANCE_ID;

if (!INSTANCE_ID) {
  throw new Error('Environment variables for INSTANCE_ID must be set!');
}

const getRowGreeting = row => {
  return row.data[COLUMN_FAMILY_ID][COLUMN_QUALIFIER][0].value;
};

(async () => {
  try {
    const bigtableClient = new Bigtable();
    const instance = bigtableClient.instance(INSTANCE_ID);
    const table = instance.table(TABLE_ID);

    const {BigtableTableAdminClient} = require('@google-cloud/bigtable').v2;
    const adminClient = new BigtableTableAdminClient();
    const projectId = await adminClient.getProjectId();

    let tableExists = true;
    try {
      await adminClient.getTable({
        name: `projects/${projectId}/instances/${INSTANCE_ID}/tables/${TABLE_ID}`,
      });
    } catch (e) {
      if (e.code === 5) {
        tableExists = false;
      }
    }
    if (!tableExists) {
      console.log(`Creating table ${TABLE_ID}`);
      const {BigtableTableAdminClient} = require('@google-cloud/bigtable').v2;
      const adminClient = new BigtableTableAdminClient();
      const projectId = await adminClient.getProjectId();
      await adminClient.createTable({
        parent: `projects/${projectId}/instances/${INSTANCE_ID}`,
        tableId: TABLE_ID,
        table: {
          columnFamilies: {
            [COLUMN_FAMILY_ID]: {
              gcRule: {
                maxNumVersions: 1,
              },
            },
          },
        },
      });
    }

    console.log('Write some greetings to the table');
    const greetings = ['Hello World!', 'Hello Bigtable!', 'Hello Node!'];
    const rowsToInsert = greetings.map((greeting, index) => ({
      key: `greeting${index}`,
      data: {
        [COLUMN_FAMILY_ID]: {
          [COLUMN_QUALIFIER]: {
            timestamp: new Date(),
            value: greeting,
          },
        },
      },
    }));
    await table.insert(rowsToInsert);

    const filter = [
      {
        column: {
          cellLimit: 1, // Only retrieve the most recent version of the cell.
        },
      },
    ];

    console.log('Reading a single row by row key');
    const [singleRow] = await table.row('greeting0').get({filter});
    console.log(`\tRead: ${getRowGreeting(singleRow)}`);

    console.log('Reading the entire table');
    const [allRows] = await table.getRows({filter});
    for (const row of allRows) {
      console.log(`\tRead: ${getRowGreeting(row)}`);
    }

    console.log('Delete the table');
    const request = {
      name: `projects/${projectId}/instances/${INSTANCE_ID}/tables/${TABLE_ID}`,
    };
    await adminClient.deleteTable(request);
  } catch (error) {
    console.error('Something went wrong:', error);
  }
})();