שלום עולם ב-Node.js

דוגמת הקוד הזו היא אפליקציית 'שלום עולם' שפועלת ב-Node.js. בדוגמה הזו מוסבר איך לבצע את הפעולות הבאות:

  • מגדירים אימות
  • מתחברים למכונה של Bigtable.
  • ליצור טבלה חדשה.
  • כתיבת נתונים בטבלה.
  • קוראים את הנתונים בחזרה.
  • מוחקים את הטבלה.

מגדירים אימות

כדי להשתמש בדוגמאות של Node.js שבדף הזה בסביבת פיתוח מקומית, מתקינים ומפעילים את ה-CLI של gcloud, ואז מגדירים את Application Default Credentials באמצעות פרטי הכניסה של המשתמש.

  1. התקינו את ה-CLI של Google Cloud.

  2. אם אתם משתמשים בספק זהויות חיצוני (IdP), קודם אתם צריכים להיכנס ל-CLI של gcloud באמצעות המאגר המאוחד לניהול זהויות.

  3. אם אתם משתמשים במעטפת מקומית, אתם צריכים ליצור פרטי כניסה לאימות מקומי עבור חשבון המשתמש:

    gcloud auth application-default login

    אם אתם משתמשים ב-Cloud Shell, אין צורך לבצע את הפעולה הזו.

    אם מוחזרת שגיאת אימות ואתם משתמשים בספק זהויות חיצוני (IdP), ודאו ש נכנסתם ל-CLI של gcloud באמצעות המאגר המאוחד לניהול זהויות.

מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

הרצת הדוגמה

בדוגמת הקוד הזו נעשה שימוש בחבילת Bigtable של ספריית הלקוח של Google Cloud ל-Node.js כדי לתקשר עם Bigtable.

כדי להריץ את תוכנית הדוגמה הזו, פועלים לפי ההוראות לדוגמה ב-GitHub.

שימוש בספריית הלקוח של Cloud עם Bigtable

אפליקציית הדוגמה מתחברת ל-Bigtable ומדגימה כמה פעולות פשוטות.

הוספת דרישה לספריית הלקוח

הדוגמה דורשת את המודול @google-cloud/bigtable, שמספק את המחלקה Bigtable.

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

התחברות ל-Bigtable

כדי להתחבר ל-Bigtable, יוצרים אובייקט חדש של Bigtable. אחר כך קוראים לשיטה instance() כדי לקבל אובייקט Instance שמייצג את מופע Bigtable.

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

יצירת טבלה

קוראים לשיטה table() של המופע כדי לקבל אובייקט Table שמייצג את הטבלה של ברכות hello world. אם הטבלה לא קיימת, קוראים לשיטה 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);
  }
})();