// Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Imports the Google Cloud client library const {Bigtable} = require('@google-cloud/bigtable'); const {TableAdminClient, GcRuleBuilder} = require('@google-cloud/bigtable').admin; const adminClient = new TableAdminClient(); async function runTableOperations(instanceID, tableID) { const bigtable = new Bigtable(); const projectId = await adminClient.getProjectId(); // The request will only work if the projectName doesn't contain the {{projectId}} token. bigtable.projectName = `projects/${projectId}`; const instance = bigtable.instance(instanceID); const table = instance.table(tableID); // Check if table exists console.log(); console.log('Checking if table exists...'); let tableExists = true; try { await adminClient.getTable({name: table.name}); } catch (e) { if (e.code === 5) { tableExists = false; } } if (!tableExists) { // Create table if does not exist console.log(`Table does not exist. Creating table ${tableID}`); const request = { parent: `projects/${projectId}/instances/${instanceID}`, tableId: tableID, table: { columnFamilies: { follows: {}, }, }, }; await adminClient.createTable(request); } else { console.log('Table exists.'); } console.log(); console.log('Listing tables in current project...'); // [START bigtable_list_tables] // List tables in current project const [tables] = await adminClient.listTables({parent: instance.name}); tables.forEach(table => { console.log(table.name); }); // [END bigtable_list_tables] console.log(); console.log('Printing table metadata...'); // [START bigtable_get_table_metadata] // Get table metadata, and apply a view to the table fields // Supported views include ID, schema or full // View defaults to schema if unspecified. const options = { view: 'id', }; const [tableMetadata] = await adminClient.getTable({ name: table.name, view: options.view, }); console.log(`Metadata: ${JSON.stringify(tableMetadata)}`); // [END bigtable_get_table_metadata] console.log(); console.log('Creating column family cf1 with max age GC rule...'); // [START bigtable_create_family_gc_max_age] // Create a column family with GC policy : maximum age // where age = current time minus cell timestamp // Define the GC rule to retain data with max age of 5 days const maxAgeRule = GcRuleBuilder.rule({ maxAge: { // Value must be atleast 1 millisecond seconds: 60 * 60 * 24 * 5, nanos: 0, }, }); let [family] = await adminClient.modifyColumnFamilies({ name: table.name, modifications: [ { id: 'cf1', create: { gcRule: maxAgeRule, }, }, ], }); console.log(`Created column family ${family.name}`); // [END bigtable_create_family_gc_max_age] console.log(); console.log('Creating column family cf2 with max versions GC rule...'); // [START bigtable_create_family_gc_max_versions] // Create a column family with GC policy : most recent N versions // where 1 = most recent version // Define the GC policy to retain only the most recent 2 versions const maxVersionsRule = GcRuleBuilder.rule({ maxVersions: 2, }); // Create a column family with given GC rule [family] = await adminClient.modifyColumnFamilies({ name: table.name, modifications: [ { id: 'cf2', create: { gcRule: maxVersionsRule, }, }, ], }); console.log(`Created column family ${family.name}`); // [END bigtable_create_family_gc_max_versions] console.log(); console.log('Creating column family cf3 with union GC rule...'); // [START bigtable_create_family_gc_union] // Create a column family with GC policy to drop data that matches at least one condition. // Define a GC rule to drop cells older than 5 days or not the most recent version const unionRule = GcRuleBuilder.union( GcRuleBuilder.rule({ maxVersions: 1, }), GcRuleBuilder.rule({ maxAge: { seconds: 60 * 60 * 24 * 5, nanos: 0, }, }), ); [family] = await adminClient.modifyColumnFamilies({ name: table.name, modifications: [ { id: 'cf3', create: { gcRule: unionRule, }, }, ], }); console.log(`Created column family ${family.name}`); // [END bigtable_create_family_gc_union] console.log(); console.log('Creating column family cf4 with intersect GC rule...'); // [START bigtable_create_family_gc_intersection] // Create a column family with GC policy to drop data that matches all conditions // GC rule: Drop cells older than 5 days AND older than the most recent 2 versions const intersectionRule = GcRuleBuilder.intersection( GcRuleBuilder.rule({ maxVersions: 2, }), GcRuleBuilder.rule({ maxAge: { seconds: 60 * 60 * 24 * 5, nanos: 0, }, }), ); [family] = await adminClient.modifyColumnFamilies({ name: table.name, modifications: [ { id: 'cf4', create: { gcRule: intersectionRule, }, }, ], }); console.log(`Created column family ${family.name}`); // [END bigtable_create_family_gc_intersection] console.log(); console.log('Creating column family cf5 with a nested GC rule...'); // [START bigtable_create_family_gc_nested] // Create a nested GC rule: // Drop cells that are either older than the 10 recent versions // OR // Drop cells that are older than a month AND older than the 2 recent versions const nestedRule = GcRuleBuilder.union( GcRuleBuilder.rule({ maxVersions: 10, }), GcRuleBuilder.intersection( GcRuleBuilder.rule({ maxVersions: 2, }), GcRuleBuilder.rule({ maxAge: { // one month seconds: 60 * 60 * 24 * 30, nanos: 0, }, }), ), ); [family] = await adminClient.modifyColumnFamilies({ name: table.name, modifications: [ { id: 'cf5', create: { gcRule: nestedRule, }, }, ], }); console.log(`Created column family ${family.name}`); // [END bigtable_create_family_gc_nested] console.log(); console.log('Printing ID and GC Rule for all column families...'); // [START bigtable_list_column_families] // List all families in the table with GC rules const [tableData2] = await adminClient.getTable({ name: table.name, view: 'FULL', }); const families = tableData2.columnFamilies; // Print ID, GC Rule for each column family for (const familyId in families) { const family = families[familyId]; const metadata = JSON.stringify(family.gcRule); console.log(`Column family: ${familyId}, Metadata: ${metadata}`); /* Sample output: Column family: projects/{{projectId}}/instances/my-instance/tables/my-table/columnFamilies/cf4, Metadata: {"gcRule":{"intersection":{"rules":[{"maxAge":{"seconds":"432000","nanos":0},"rule":"maxAge"},{"maxNumVersions":2,"rule":"maxNumVersions"}]},"rule":"intersection"}} */ } // [END bigtable_list_column_families] console.log('\nUpdating column family cf1 GC rule...'); // [START bigtable_update_gc_rule] // Update the column family metadata to update the GC rule // Update a column family GC rule const updatedMetadata = GcRuleBuilder.rule({ maxNumVersions: 1, }); const [apiResponse] = await adminClient.modifyColumnFamilies({ name: table.name, modifications: [ { id: 'cf1', update: { gcRule: updatedMetadata, }, }, ], }); console.log(`Updated GC rule: ${JSON.stringify(apiResponse)}`); // [END bigtable_update_gc_rule] console.log('\nPrint updated column family cf1 GC rule...'); // [START bigtable_family_get_gc_rule] // Retrieve column family metadata (Id, column family GC rule) const [tableData] = await adminClient.getTable({ name: table.name, view: 'FULL', }); const metadata = tableData.columnFamilies['cf1'].gcRule; console.log(`Metadata: ${JSON.stringify(metadata)}`); // [END bigtable_family_get_gc_rule] console.log('\nDelete a column family cf2...'); // [START bigtable_delete_family] // Delete a column family await adminClient.modifyColumnFamilies({ name: table.name, modifications: [ { id: 'cf2', drop: true, }, ], }); console.log('cf2 deleted successfully\n'); // [END bigtable_delete_family] console.log( 'Run node $0 delete --instance [instanceID] --table [tableID] to delete the table.\n', ); } async function deleteTable(instanceID, tableID) { // const instanceID = "my-instance"; // const tableID = "my-bigtable-ID"; const {BigtableTableAdminClient} = require('@google-cloud/bigtable').v2; const adminClient = new BigtableTableAdminClient(); const projectId = await adminClient.getProjectId(); // [START bigtable_delete_table] // Delete the entire table console.log('Delete the table.'); await adminClient.deleteTable({ name: `projects/${projectId}/instances/${instanceID}/tables/${tableID}`, }); console.log(`Table deleted: ${tableID}`); // [END bigtable_delete_table] } require('yargs') .demand(1) .command( 'run', 'Create a table (if does not exist) and run basic table operations.', {}, argv => runTableOperations(argv.instance, argv.table), ) .example( 'node $0 run --instance [instanceID] --table [tableID]', 'Create a table (if does not exist) and run basic table operations.', ) .wrap(120) .command('delete', 'Delete table.', {}, argv => deleteTable(argv.instance, argv.table), ) .example( 'node $0 delete --instance [instanceID] --table [tableID]', 'Delete a table.', ) .wrap(120) .nargs('instance', 1) .nargs('table', 1) .describe('instance', 'Cloud Bigtable Instance ID') .describe('table', 'Cloud Bigtable Table ID') .demandOption(['instance', 'table']) .recommendCommands() .epilogue('For more information, see https://cloud.google.com/bigtable/docs') .help() .strict().argv;