Node.js hello world

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

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

設定驗證方法

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

  1. 安裝 Google Cloud CLI。

  2. 如果您使用外部識別資訊提供者 (IdP),請先 使用聯合身分登入 gcloud CLI。

  3. 如果您使用本機殼層,請為使用者帳戶建立本機驗證憑證:

    gcloud auth application-default login

    如果您使用的是 Cloud Shell,則不必執行這項操作。

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

詳情請參閱「 為本機開發環境設定驗證機制」。

執行範例

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

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

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

範例應用程式會連線至 Bigtable,並示範一些簡單的操作。

須使用用戶端程式庫

這個範例需要 @google-cloud/bigtable 模組,該模組提供 Bigtable 類別。

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