Google Cloud Bigtable C++ Client 2.13.0
A C++ Client Library for Google Cloud Bigtable
Loading...
Searching...
No Matches
Getting Started with Bigtable

This example is a very simple "hello world" application, written in C++, that illustrates how to:

  • Connect to a Cloud Bigtable instance.
  • Create a new table.
  • Write data to the table.
  • Read the data back.
  • Delete the table.

Running the example

This example uses the Cloud Bigtable C++ Client Library to communicate with Cloud Bigtable.

To run the example program, follow the instructions for the example on GitHub.

Including the Necessary Headers

The example uses the following headers:

#include "google/cloud/bigtable/admin/bigtable_table_admin_client.h"
#include "google/cloud/bigtable/resource_names.h"
#include "google/cloud/bigtable/table.h"

Introduce aliases to make the example more readable

namespace cbt = ::google::cloud::bigtable;
namespace cbta = ::google::cloud::bigtable_admin;
using ::google::cloud::StatusOr;

Connecting to Cloud Bigtable to manage tables

To manage tables, connect to Cloud Bigtable using bigtable_admin::MakeBigtableTableAdminConnection():

// Connect to the Cloud Bigtable Admin API.
cbta::BigtableTableAdminClient table_admin(
cbta::MakeBigtableTableAdminConnection());
// Create an object to access the Cloud Bigtable Data API.
cbt::Table table(cbt::MakeDataConnection(),
cbt::TableResource(project_id, instance_id, table_id));
See also
bigtable_admin::BigtableTableAdminClient for more information on how to perform administrative operations on tables.

Creating a table

Create a table with BigtableTableAdminClient::CreateTable():

// Define the desired schema for the Table.
google::bigtable::admin::v2::Table t;
auto& families = *t.mutable_column_families();
families["family"].mutable_gc_rule()->set_max_num_versions(1);
// Create a table.
std::string instance_name = cbt::InstanceName(project_id, instance_id);
StatusOr<google::bigtable::admin::v2::Table> schema =
table_admin.CreateTable(instance_name, table_id, std::move(t));
See also
bigtable::BigtableTableAdminClient for additional operations to list, read, modify, and delete tables.
https://cloud.google.com/bigtable/docs/overview for an overview of the Cloud Bigtable storage model, including an introduction to important Cloud Bigtable concepts, such as row keys, column families, columns, and cells.
https://cloud.google.com/bigtable/docs/schema-design for suggestions on how to design your table schema.

Connecting to Cloud Bigtable to read and write data

To read and write data, connect to Cloud Bigtable using bigtable::MakeDataConnection():

// Create an object to access the Cloud Bigtable Data API.
cbt::Table table(cbt::MakeDataConnection(),
cbt::TableResource(project_id, instance_id, table_id));
See also
bigtable::Table for the functions to read and write data to Cloud Bigtable.

Writing Rows to a table

To write a single row use Table::Apply():

std::vector<std::string> greetings{"Hello World!", "Hello Cloud Bigtable!",
"Hello C++!"};
int i = 0;
for (auto const& greeting : greetings) {
// Each row has a unique row key.
//
// Note: This example uses sequential numeric IDs for simplicity, but
// this can result in poor performance in a production application.
// Since rows are stored in sorted order by key, sequential keys can
// result in poor distribution of operations across nodes.
//
// For more information about how to design a Bigtable schema for the
// best performance, see the documentation:
//
// https://cloud.google.com/bigtable/docs/schema-design
std::string row_key = "key-" + std::to_string(i);
google::cloud::Status status = table.Apply(cbt::SingleRowMutation(
std::move(row_key), cbt::SetCell("family", "c0", greeting)));
if (!status.ok()) throw std::runtime_error(status.message());
++i;
}
std::string const & message() const
See also
Table::BulkApply() to modify multiple rows in a single request.
DeleteFromFamily(), DeleteFromRow(), DeleteFromColumn() to delete some (or all) the cells in a row.
One of the overloads for SetCell() allows setting an explicit timestamp, which is an idempotent mutation and thus can be automatically retried on transient errors.

Creating filter for the column families

Use a filter to select only a subset of the cells in a row, in this case, we will select only the rows in the family column family and the c0 column:

cbt::Filter filter = cbt::Filter::ColumnRangeClosed("family", "c0", "c0");
See also
bigtable::Filter to filter the column families, columns, and even the timestamps returned by ReadRow().

Reading data back: get a single row by its key

Get a row directly using its key with Table::ReadRow():

StatusOr<std::pair<bool, cbt::Row>> result = table.ReadRow("key-0", filter);
if (!result) throw std::move(result).status();
if (!result->first) {
std::cout << "Cannot find row 'key-0' in the table: " << table.table_name()
<< "\n";
return;
}
cbt::Cell const& cell = result->second.cells().front();
std::cout << cell.family_name() << ":" << cell.column_qualifier() << " @ "
<< cell.timestamp().count() << "us\n"
<< '"' << cell.value() << '"' << "\n";
See also
bigtable::Filter to filter the column families, columns, and even the timestamps returned by ReadRow().
Table::ReadRows() to iterate over multiple rows.

Reading data back: scanning all table rows

Use Table::ReadRows() to scan all of the rows in a table.

for (auto& row : table.ReadRows(cbt::RowRange::InfiniteRange(),
cbt::Filter::PassAllFilter())) {
if (!row) throw std::move(row).status();
std::cout << row->row_key() << ":\n";
for (cbt::Cell const& c : row->cells()) {
std::cout << "\t" << c.family_name() << ":" << c.column_qualifier()
<< " @ " << c.timestamp().count() << "us\n"
<< "\t\"" << c.value() << '"' << "\n";
}
}
See also
bigtable::RowRange to read only a portion of the table.
bigtable::RowSet to form arbitrary groups of ranges and specific row keys in a Table::ReadRows() request.
bigtable::Row for details of the contents in a row.

Deleting a table

Delete a table with BigtableTableAdminClient::DeleteTable().

google::cloud::Status status = table_admin.DeleteTable(table.table_name());
if (!status.ok()) throw std::runtime_error(status.message());

Putting it all together

Here is the full example

#include "google/cloud/bigtable/admin/bigtable_table_admin_client.h"
#include "google/cloud/bigtable/resource_names.h"
#include "google/cloud/bigtable/table.h"
#include "google/cloud/bigtable/examples/bigtable_examples_common.h"
#include "google/cloud/bigtable/testing/random_names.h"
#include "google/cloud/internal/getenv.h"
#include "google/cloud/internal/random.h"
#include "google/cloud/log.h"
#include <iostream>
namespace {
using ::google::cloud::bigtable::examples::Usage;
void BigtableHelloWorld(std::vector<std::string> const& argv) {
if (argv.size() != 3) {
throw Usage{"hello-world <project-id> <instance-id> <table-id>"};
}
std::string const& project_id = argv[0];
std::string const& instance_id = argv[1];
std::string const& table_id = argv[2];
// Create a namespace alias to make the code easier to read.
namespace cbt = ::google::cloud::bigtable;
namespace cbta = ::google::cloud::bigtable_admin;
using ::google::cloud::StatusOr;
// Connect to the Cloud Bigtable Admin API.
cbta::BigtableTableAdminClient table_admin(
cbta::MakeBigtableTableAdminConnection());
// Create an object to access the Cloud Bigtable Data API.
cbt::Table table(cbt::MakeDataConnection(),
cbt::TableResource(project_id, instance_id, table_id));
// Define the desired schema for the Table.
google::bigtable::admin::v2::Table t;
auto& families = *t.mutable_column_families();
families["family"].mutable_gc_rule()->set_max_num_versions(1);
// Create a table.
std::string instance_name = cbt::InstanceName(project_id, instance_id);
StatusOr<google::bigtable::admin::v2::Table> schema =
table_admin.CreateTable(instance_name, table_id, std::move(t));
// Modify (and create if necessary) a row.
std::vector<std::string> greetings{"Hello World!", "Hello Cloud Bigtable!",
"Hello C++!"};
int i = 0;
for (auto const& greeting : greetings) {
// Each row has a unique row key.
//
// Note: This example uses sequential numeric IDs for simplicity, but
// this can result in poor performance in a production application.
// Since rows are stored in sorted order by key, sequential keys can
// result in poor distribution of operations across nodes.
//
// For more information about how to design a Bigtable schema for the
// best performance, see the documentation:
//
// https://cloud.google.com/bigtable/docs/schema-design
std::string row_key = "key-" + std::to_string(i);
google::cloud::Status status = table.Apply(cbt::SingleRowMutation(
std::move(row_key), cbt::SetCell("family", "c0", greeting)));
if (!status.ok()) throw std::runtime_error(status.message());
++i;
}
cbt::Filter filter = cbt::Filter::ColumnRangeClosed("family", "c0", "c0");
// Read a single row.
StatusOr<std::pair<bool, cbt::Row>> result = table.ReadRow("key-0", filter);
if (!result) throw std::move(result).status();
if (!result->first) {
std::cout << "Cannot find row 'key-0' in the table: " << table.table_name()
<< "\n";
return;
}
cbt::Cell const& cell = result->second.cells().front();
std::cout << cell.family_name() << ":" << cell.column_qualifier() << " @ "
<< cell.timestamp().count() << "us\n"
<< '"' << cell.value() << '"' << "\n";
// Read all rows.
for (auto& row : table.ReadRows(cbt::RowRange::InfiniteRange(),
cbt::Filter::PassAllFilter())) {
if (!row) throw std::move(row).status();
std::cout << row->row_key() << ":\n";
for (cbt::Cell const& c : row->cells()) {
std::cout << "\t" << c.family_name() << ":" << c.column_qualifier()
<< " @ " << c.timestamp().count() << "us\n"
<< "\t\"" << c.value() << '"' << "\n";
}
}
// Delete the table
google::cloud::Status status = table_admin.DeleteTable(table.table_name());
if (!status.ok()) throw std::runtime_error(status.message());
}
void RunAll(std::vector<std::string> const& argv) {
namespace examples = ::google::cloud::bigtable::examples;
namespace cbt = ::google::cloud::bigtable;
if (!argv.empty()) throw Usage{"auto"};
if (!examples::RunAdminIntegrationTests()) return;
examples::CheckEnvironmentVariablesAreSet({
"GOOGLE_CLOUD_PROJECT",
"GOOGLE_CLOUD_CPP_BIGTABLE_TEST_INSTANCE_ID",
});
auto const project_id =
google::cloud::internal::GetEnv("GOOGLE_CLOUD_PROJECT").value();
auto const instance_id = google::cloud::internal::GetEnv(
"GOOGLE_CLOUD_CPP_BIGTABLE_TEST_INSTANCE_ID")
.value();
auto generator = google::cloud::internal::DefaultPRNG(std::random_device{}());
auto table_id = cbt::testing::RandomTableId(generator);
std::cout << "\nRunning the BigtableHelloWorld() example" << std::endl;
BigtableHelloWorld({project_id, instance_id, table_id});
}
} // namespace
int main(int argc, char* argv[]) try {
google::cloud::bigtable::examples::Example example({
{"auto", RunAll},
{"hello-world", BigtableHelloWorld},
});
return example.Run(argc, argv);
} catch (std::exception const& ex) {
std::cerr << ex.what() << "\n";
return 1;
}
static LogSink & Instance()