From 886af7a23d5d42b58448358f572409d71faafdb8 Mon Sep 17 00:00:00 2001 From: danieljbruce Date: Mon, 20 Jun 2022 10:00:51 -0400 Subject: [PATCH] samples: Bigtable deletion code samples (#1078) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * First code samples * Add the end exclude tag * Update the comments * Add integration test for delete code snippets * Three more test cases * Add the final test case * Add header * linting fix * Add call options * Use before instead of beforeEach * PR updates * Remove comment that is unimportant * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * remove start exclude and end exclude tags * row range feedback * Delete row snapshot * Slight change to fix samples test * switch batch delete to batch insert * Removed line of code that is shortening timestamp * Correct snapshot * Revert "Removed line of code that is shortening timestamp" This reverts commit 96adcdbee42e26e53aa270a43713732342cf902c. * Fix to short snapshot. * Revert "Fix to short snapshot." This reverts commit 73736e694014e0730acba2635186b6659961a610. * Revert "Correct snapshot" This reverts commit f86b6fab4207aba417e974d147f3f048a423208f. * Revert "switch batch delete to batch insert" This reverts commit 72cef5d5da00041cd09a49d155f05c4402143e3f. * streaming and batching changes Co-authored-by: Owl Bot --- README.md | 1 + samples/README.md | 18 +++ samples/__snapshots__/deletes.js | 183 ++++++++++++++++++++++++ samples/deleteSnippets.js | 156 +++++++++++++++++++++ samples/test/deletes.js | 230 +++++++++++++++++++++++++++++++ 5 files changed, 588 insertions(+) create mode 100644 samples/__snapshots__/deletes.js create mode 100644 samples/deleteSnippets.js create mode 100644 samples/test/deletes.js diff --git a/README.md b/README.md index d40b6b8b5..90dbfbfb9 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,7 @@ Samples are in the [`samples/`](https://github.com/googleapis/nodejs-bigtable/tr | Sample | Source Code | Try it | | --------------------------- | --------------------------------- | ------ | +| Delete Snippets | [source code](https://github.com/googleapis/nodejs-bigtable/blob/main/samples/deleteSnippets.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-bigtable&page=editor&open_in_editor=samples/deleteSnippets.js,samples/README.md) | | Filter Snippets | [source code](https://github.com/googleapis/nodejs-bigtable/blob/main/samples/filterSnippets.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-bigtable&page=editor&open_in_editor=samples/filterSnippets.js,samples/README.md) | | Instances | [source code](https://github.com/googleapis/nodejs-bigtable/blob/main/samples/instances.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-bigtable&page=editor&open_in_editor=samples/instances.js,samples/README.md) | | Quickstart | [source code](https://github.com/googleapis/nodejs-bigtable/blob/main/samples/quickstart.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-bigtable&page=editor&open_in_editor=samples/quickstart.js,samples/README.md) | diff --git a/samples/README.md b/samples/README.md index 1f65d7a59..357d758b0 100644 --- a/samples/README.md +++ b/samples/README.md @@ -12,6 +12,7 @@ * [Before you begin](#before-you-begin) * [Samples](#samples) + * [Delete Snippets](#delete-snippets) * [Filter Snippets](#filter-snippets) * [Instances](#instances) * [Quickstart](#quickstart) @@ -37,6 +38,23 @@ Before running the samples, make sure you've followed the steps outlined in +### Delete Snippets + +View the [source code](https://github.com/googleapis/nodejs-bigtable/blob/main/samples/deleteSnippets.js). + +[![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-bigtable&page=editor&open_in_editor=samples/deleteSnippets.js,samples/README.md) + +__Usage:__ + + +`node samples/deleteSnippets.js` + + +----- + + + + ### Filter Snippets View the [source code](https://github.com/googleapis/nodejs-bigtable/blob/main/samples/filterSnippets.js). diff --git a/samples/__snapshots__/deletes.js b/samples/__snapshots__/deletes.js new file mode 100644 index 000000000..796485308 --- /dev/null +++ b/samples/__snapshots__/deletes.js @@ -0,0 +1,183 @@ +// Copyright 2022 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. + +exports['deletes should delete column from a row 1'] = ` +Column Family stats_summary +\tconnected_cell: 1 @1559347200000000 +\tconnected_wifi: 1 @1559347200000000 +\tos_build: PQ2A.190405.003 @1559347200000000 +Column Family cell_plan +\tdata_plan_01gb: @1559347200000000 +Column Family stats_summary +\tconnected_cell: 1 @1559347200000000 +\tconnected_wifi: 1 @1559347200000000 +\tos_build: PQ2A.190405.004 @1559347200000000 +Column Family cell_plan +\tdata_plan_05gb: @1559347200000000 +Column Family stats_summary +\tconnected_cell: 0 @1559347200000000 +\tconnected_wifi: 1 @1559347200000000 +\tos_build: PQ2A.190406.000 @1559347200000000 +Column Family cell_plan +\tdata_plan_05gb: @1559347200000000 +Column Family stats_summary +\tconnected_cell: 1 @1559347200000000 +\tconnected_wifi: 1 @1559347200000000 +\tos_build: PQ2A.190401.002 @1559347200000000 +Column Family cell_plan +\tdata_plan_10gb: @1559347200000000 +Column Family stats_summary +\tconnected_cell: 1 @1559347200000000 +\tconnected_wifi: 0 @1559347200000000 +\tos_build: PQ2A.190406.000 @1559347200000000 +Column Family cell_plan +\tdata_plan_10gb: @1559347200000000 + + +`; + +exports['deletes should delete column family from a row 1'] = ` +Column Family stats_summary +\tconnected_cell: 1 @1559347200000000 +\tconnected_wifi: 1 @1559347200000000 +\tos_build: PQ2A.190405.003 @1559347200000000 +Column Family stats_summary +\tconnected_cell: 1 @1559347200000000 +\tconnected_wifi: 1 @1559347200000000 +\tos_build: PQ2A.190405.004 @1559347200000000 +Column Family cell_plan +\tdata_plan_05gb: @1559347200000000 +Column Family stats_summary +\tconnected_cell: 0 @1559347200000000 +\tconnected_wifi: 1 @1559347200000000 +\tos_build: PQ2A.190406.000 @1559347200000000 +Column Family cell_plan +\tdata_plan_05gb: @1559347200000000 +Column Family stats_summary +\tconnected_cell: 1 @1559347200000000 +\tconnected_wifi: 1 @1559347200000000 +\tos_build: PQ2A.190401.002 @1559347200000000 +Column Family cell_plan +\tdata_plan_10gb: @1559347200000000 +Column Family stats_summary +\tconnected_cell: 1 @1559347200000000 +\tconnected_wifi: 0 @1559347200000000 +\tos_build: PQ2A.190406.000 @1559347200000000 +Column Family cell_plan +\tdata_plan_10gb: @1559347200000000 + + +`; + +exports['deletes should delete a row 1'] = ` +Column Family stats_summary +\tconnected_cell: 1 @1559347200000000 +\tconnected_wifi: 1 @1559347200000000 +\tos_build: PQ2A.190405.004 @1559347200000000 +Column Family cell_plan +\tdata_plan_05gb: @1559347200000000 +Column Family stats_summary +\tconnected_cell: 0 @1559347200000000 +\tconnected_wifi: 1 @1559347200000000 +\tos_build: PQ2A.190406.000 @1559347200000000 +Column Family cell_plan +\tdata_plan_05gb: @1559347200000000 +Column Family stats_summary +\tconnected_cell: 1 @1559347200000000 +\tconnected_wifi: 1 @1559347200000000 +\tos_build: PQ2A.190401.002 @1559347200000000 +Column Family cell_plan +\tdata_plan_10gb: @1559347200000000 +Column Family stats_summary +\tconnected_cell: 1 @1559347200000000 +\tconnected_wifi: 0 @1559347200000000 +\tos_build: PQ2A.190406.000 @1559347200000000 +Column Family cell_plan +\tdata_plan_10gb: @1559347200000000 + + +`; + +exports['deletes should stream rows and then do a batch delete 1'] = ` +Column Family stats_summary +\tconnected_cell: 1 @1559347200000000 +\tconnected_wifi: 1 @1559347200000000 +\tos_build: PQ2A.190405.004 @1559347200000000 +Column Family stats_summary +\tconnected_cell: 0 @1559347200000000 +\tconnected_wifi: 1 @1559347200000000 +\tos_build: PQ2A.190406.000 @1559347200000000 +Column Family stats_summary +\tconnected_cell: 1 @1559347200000000 +\tconnected_wifi: 1 @1559347200000000 +\tos_build: PQ2A.190401.002 @1559347200000000 +Column Family cell_plan +\tdata_plan_10gb: @1559347200000000 +Column Family stats_summary +\tconnected_cell: 1 @1559347200000000 +\tconnected_wifi: 0 @1559347200000000 +\tos_build: PQ2A.190406.000 @1559347200000000 +Column Family cell_plan +\tdata_plan_10gb: @1559347200000000 + + +`; + +exports['deletes should check and mutate 1'] = ` +Column Family stats_summary +\tconnected_cell: 1 @1559347200000000 +\tconnected_wifi: 1 @1559347200000000 +\tos_build: PQ2A.190405.004 @1559347200000000 +Column Family stats_summary +\tconnected_cell: 0 @1559347200000000 +\tconnected_wifi: 1 @1559347200000000 +\tos_build: PQ2A.190406.000 @1559347200000000 +Column Family stats_summary +\tconnected_cell: 1 @1559347200000000 +\tconnected_wifi: 1 @1559347200000000 +\tos_build: PQ2A.190401.002 @1559347200000000 +Column Family cell_plan +\tdata_plan_10gb: @1559347200000000 +Column Family stats_summary +\tconnected_cell: 1 @1559347200000000 +\tconnected_wifi: 0 @1559347200000000 +\tos_build: PQ2A.190406.000 @1559347200000000 +Column Family cell_plan +\tdata_plan_10gb: @1559347200000000 + + +`; + +exports['deletes should delete a whole range of rows 1'] = ` +Column Family stats_summary +\tconnected_cell: 1 @1559347200000000 +\tconnected_wifi: 1 @1559347200000000 +\tos_build: PQ2A.190405.004 @1559347200000000 +Column Family stats_summary +\tconnected_cell: 0 @1559347200000000 +\tconnected_wifi: 1 @1559347200000000 +\tos_build: PQ2A.190406.000 @1559347200000000 + + +`; + +exports['deletes should delete a column family 1'] = ` + + +`; + +exports['deletes should delete a table 1'] = ` +[ false ] + +`; diff --git a/samples/deleteSnippets.js b/samples/deleteSnippets.js new file mode 100644 index 000000000..93f1dcd03 --- /dev/null +++ b/samples/deleteSnippets.js @@ -0,0 +1,156 @@ +// Copyright 2022 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. + +'use strict'; + +async function main( + instanceId = 'YOUR_INSTANCE_ID', + tableId = 'YOUR_TABLE_ID', + deleteType = 'readRow' +) { + // [START bigtable_deletes_print] + const {Bigtable} = require('@google-cloud/bigtable'); + const bigtable = new Bigtable(); + + // TODO: We need to import Mutation.methods.DELETE from mutation.ts, but I guess we need to compile typescript? + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const instanceId = 'YOUR_INSTANCE_ID'; + // const tableId = 'YOUR_TABLE_ID'; + const instance = bigtable.instance(instanceId); + const table = instance.table(tableId); + + switch (deleteType) { + case 'deleteFromColumn': { + // [START bigtable_delete_from_column] + await table.mutate({ + key: 'phone#4c410523#20190501', + method: 'delete', + data: { + column: 'cell_plan:data_plan_05gb', + }, + }); + await printRows(); + // [END bigtable_delete_from_column] + break; + } + case 'deleteFromFamily': { + // [START bigtable_delete_from_column_family] + await table.mutate({ + key: 'phone#4c410523#20190501', + method: 'delete', + data: { + column: 'cell_plan', + }, + }); + await printRows(); + // [END bigtable_delete_from_column_family] + break; + } + case 'deleteFromRow': { + // [START bigtable_deletes_from_row] + const row = table.row('phone#4c410523#20190501'); + await row.delete(); + await printRows(); + // [END bigtable_deletes_from_row] + break; + } + case 'streamingAndBatching': { + // [START bigtable_streaming_and_batching] + const rows = (await table.getRows({limit: 2}))[0]; + const entries = rows.map(row => { + return { + key: row.id, + method: 'delete', + data: { + column: 'cell_plan:data_plan_05gb', + }, + }; + }); + await table.mutate(entries); + await printRows(); + // [END bigtable_streaming_and_batching] + break; + } + case 'checkAndMutate': { + // [START bigtable_check_and_mutate] + const row = table.row('phone#4c410523#20190502'); + await row.filter( + { + column: 'data_plan_05gb', + }, + { + onMatch: { + key: 'phone#4c410523#20190502', + method: 'delete', + }, + } + ); + await printRows(); + // [END bigtable_check_and_mutate] + break; + } + case 'dropRowRange': { + // [START bigtable_drop_row_range] + await table.deleteRows('phone#5c10102'); + await printRows(); + // [END bigtable_drop_row_range] + break; + } + case 'deleteColumnFamily': { + // [START bigtable_delete_column_family] + const cf = table.family('stats_summary'); + await cf.delete(); + await printRows(); + // [END bigtable_delete_column_family] + break; + } + case 'deleteTable': { + // [START bigtable_delete_table] + await table.delete(); + console.log(await table.exists({})); + // [END bigtable_delete_table] + break; + } + } + + async function printRows() { + const rows = (await table.getRows({}))[0]; + for (const row of rows) { + const rowData = row.data; + for (const columnFamily of Object.keys(rowData)) { + const columnFamilyData = rowData[columnFamily]; + console.log(`Column Family ${columnFamily}`); + + for (const columnQualifier of Object.keys(columnFamilyData)) { + const col = columnFamilyData[columnQualifier]; + + for (const cell of col) { + const labels = cell.labels.length + ? ` [${cell.labels.join(',')}]` + : ''; + console.log( + `\t${columnQualifier}: ${cell.value} @${cell.timestamp}${labels}` + ); + } + } + } + } + console.log(); + } +} +// [END bigtable_deletes_print] + +main(...process.argv.slice(2)); diff --git a/samples/test/deletes.js b/samples/test/deletes.js new file mode 100644 index 000000000..a41ed856d --- /dev/null +++ b/samples/test/deletes.js @@ -0,0 +1,230 @@ +// Copyright 2022 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. + +'use strict'; + +const uuid = require('uuid'); +const snapshot = require('snap-shot-it'); +const {describe, it, before} = require('mocha'); +const cp = require('child_process'); +const {obtainTestInstance} = require('./util'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); +const TABLE_ID = `mobile-time-series-${uuid.v4()}`.substr(0, 30); // Bigtable naming rules + +describe('deletes', async () => { + let table; + let INSTANCE_ID; + const TIMESTAMP = new Date(2019, 5, 1); + TIMESTAMP.setUTCHours(0); + + before(async () => { + const instance = await obtainTestInstance(); + INSTANCE_ID = instance.id; + table = instance.table(TABLE_ID); + const tableExists = (await table.exists({}))[0]; + if (tableExists) { + await table.delete({}); + } + await table.create(); + await table.createFamily('stats_summary'); + await table.createFamily('cell_plan'); + + const rowsToInsert = [ + { + key: 'phone#4c410523#20190501', + data: { + stats_summary: { + connected_cell: { + value: 1, + labels: [], + timestamp: TIMESTAMP, + }, + connected_wifi: { + value: 1, + labels: [], + timestamp: TIMESTAMP, + }, + os_build: { + value: 'PQ2A.190405.003', + labels: [], + timestamp: TIMESTAMP, + }, + }, + cell_plan: { + data_plan_01gb: { + value: true, + labels: [], + timestamp: TIMESTAMP, + }, + data_plan_05gb: { + value: true, + labels: [], + timestamp: TIMESTAMP, + }, + }, + }, + }, + { + key: 'phone#4c410523#20190502', + data: { + stats_summary: { + connected_cell: { + value: 1, + labels: [], + timestamp: TIMESTAMP, + }, + connected_wifi: { + value: 1, + labels: [], + timestamp: TIMESTAMP, + }, + os_build: { + value: 'PQ2A.190405.004', + labels: [], + timestamp: TIMESTAMP, + }, + }, + cell_plan: { + data_plan_05gb: { + value: true, + labels: [], + timestamp: TIMESTAMP, + }, + }, + }, + }, + { + key: 'phone#4c410523#20190505', + data: { + stats_summary: { + connected_cell: { + value: 0, + labels: [], + timestamp: TIMESTAMP, + }, + connected_wifi: { + value: 1, + labels: [], + timestamp: TIMESTAMP, + }, + os_build: { + value: 'PQ2A.190406.000', + labels: [], + timestamp: TIMESTAMP, + }, + }, + cell_plan: { + data_plan_05gb: { + value: true, + labels: [], + timestamp: TIMESTAMP, + }, + }, + }, + }, + { + key: 'phone#5c10102#20190501', + data: { + stats_summary: { + connected_cell: { + value: 1, + labels: [], + timestamp: TIMESTAMP, + }, + connected_wifi: { + value: 1, + labels: [], + timestamp: TIMESTAMP, + }, + os_build: { + value: 'PQ2A.190401.002', + labels: [], + timestamp: TIMESTAMP, + }, + }, + cell_plan: { + data_plan_10gb: { + value: true, + labels: [], + timestamp: TIMESTAMP, + }, + }, + }, + }, + { + key: 'phone#5c10102#20190502', + data: { + stats_summary: { + connected_cell: { + value: 1, + labels: [], + timestamp: TIMESTAMP, + }, + connected_wifi: { + value: 0, + labels: [], + timestamp: TIMESTAMP, + }, + os_build: { + value: 'PQ2A.190406.000', + labels: [], + timestamp: TIMESTAMP, + }, + }, + cell_plan: { + data_plan_10gb: { + value: true, + labels: [], + timestamp: TIMESTAMP, + }, + }, + }, + }, + ]; + + await table.insert(rowsToInsert); + }); + + function runAndSnapshot(cmd) { + const deleteSnippetsCommand = `node deleteSnippets ${INSTANCE_ID} ${TABLE_ID} ${cmd}`; + const stdout = execSync(deleteSnippetsCommand); + snapshot(stdout); + } + + it('should delete column from a row', async () => { + runAndSnapshot('deleteFromColumn'); + }); + it('should delete column family from a row', async () => { + runAndSnapshot('deleteFromFamily'); + }); + it('should delete a row', async () => { + runAndSnapshot('deleteFromRow'); + }); + it('should stream rows and then do a batch delete', async () => { + runAndSnapshot('streamingAndBatching'); + }); + it('should check and mutate', async () => { + runAndSnapshot('checkAndMutate'); + }); + it('should delete a whole range of rows', async () => { + runAndSnapshot('dropRowRange'); + }); + it('should delete a column family', async () => { + runAndSnapshot('deleteColumnFamily'); + }); + it('should delete a table', async () => { + runAndSnapshot('deleteTable'); + }); +});