Node.js の Hello World

このコードサンプルは、Node.js で動作する「Hello World」アプリケーションです。このサンプルでは、次のタスクを行う方法を説明します。

  • 認証の設定
  • Bigtable インスタンスに接続する
  • 新しいテーブルを作成する
  • テーブルにデータを書き込む
  • そのデータを読み取る
  • テーブルを削除する

認証の設定

このページの Node.js サンプルをローカル開発環境から使用するには、gcloud CLI をインストールして初期化し、自身のユーザー認証情報を使用してアプリケーションのデフォルト認証情報を設定してください。

  1. Google Cloud CLI をインストールします。
  2. gcloud CLI を初期化するには:

    gcloud init
  3. Google アカウントのローカル認証情報を作成します。

    gcloud auth application-default login

詳細については、 ローカル開発環境の認証の設定 をご覧ください。

サンプルの実行

このコードサンプルでは、Node.js 用 Google Cloud クライアント ライブラリBigtable パッケージを使用して Bigtable と通信します。

このサンプル プログラムを実行するには、GitHub でのサンプルの手順に沿って操作してください。

Bigtable での Cloud クライアント ライブラリの使用

このサンプル アプリケーションは Bigtable に接続して、いくつかの単純なオペレーションを行います。

必要なクライアント ライブラリ

このサンプルでは、Bigtable クラスを提供する @google-cloud/bigtable モジュールが必要です。

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

Bigtable への接続

Bigtable に接続するには、新しい Bigtable オブジェクトを作成します。次に、その instance() メソッドを呼び出して、Bigtable インスタンスを表す Instance オブジェクトを取得します。

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

テーブルの作成

インスタンスの table() メソッドを呼び出して、「Hello World」というあいさつ用のテーブルを表す Table オブジェクトを取得します。テーブルが存在しない場合は、テーブルの create() メソッドを呼び出して、各値の 1 つのバージョンを保持する単一の列ファミリーを持つテーブルを作成します。

const table = instance.table(TABLE_ID);
const [tableExists] = await table.exists();
if (!tableExists) {
  console.log(`Creating table ${TABLE_ID}`);
  const options = {
    families: [
      {
        name: COLUMN_FAMILY_ID,
        rule: {
          versions: 1,
        },
      },
    ],
  };
  await table.create(options);
}

テーブルへの行の書き込み

テーブルの新しい行を作成するために、あいさつの文字列の配列を使用します。配列の 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() メソッドを呼び出してフィルタを渡し、その行の各値の 1 つのバージョンを取得します。

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

すべてのテーブル行のスキャン

テーブルのすべての行を取得するには、テーブルの getRows() メソッドを呼び出して、フィルタを渡します。フィルタを渡しているため、Bigtable は各値の 1 つのバージョンのみを返します。

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');
await table.delete();

すべてを組み合わせる

コメントなしの完全なコードサンプルを以下に示します。



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 [tableExists] = await table.exists();
    if (!tableExists) {
      console.log(`Creating table ${TABLE_ID}`);
      const options = {
        families: [
          {
            name: COLUMN_FAMILY_ID,
            rule: {
              versions: 1,
            },
          },
        ],
      };
      await table.create(options);
    }

    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');
    await table.delete();
  } catch (error) {
    console.error('Something went wrong:', error);
  }
})();