C++ 版 Hello World
本示例是一个简单的“hello world”应用,采用 C++ 编写而成,旨在说明如何完成以下操作:
- 连接到 Cloud Bigtable 实例。
- 新建一个表。
- 将数据写入表中。
- 重新读取这些数据。
- 删除表。
运行示例
此示例使用 C++ 版 Google Cloud 客户端库的 Cloud Bigtable 软件包与 Bigtable 通信。
要运行此示例程序,请按照 GitHub 上的说明操作。
将 Google Cloud 客户端库与 Bigtable 搭配使用
示例应用会连接到 Bigtable 并演示一些简单操作。
安装和导入客户端库
从 GitHub 中下载或克隆 Cloud Bigtable C++ 客户端库,然后对其进行编译。按照顶层 README 中的编译器说明进行操作。
添加必需的标头。
#include "google/cloud/bigtable/admin/bigtable_table_admin_client.h"
#include "google/cloud/bigtable/resource_names.h"
#include "google/cloud/bigtable/table.h"
连接到 Bigtable
使用 MakeBigtableTableAdminConnection()
构建 BigtableTableAdminClient
,用于创建表。
// Connect to the Cloud Bigtable Admin API.
cbta::BigtableTableAdminClient table_admin(
cbta::MakeBigtableTableAdminConnection());
//! [connect data]
// Create an object to access the Cloud Bigtable Data API.
cbt::Table table(cbt::MakeDataConnection(),
cbt::TableResource(project_id, instance_id, table_id));
//! [connect data]
创建表
为包含一个列族的表定义架构。为列族设置垃圾回收规则,使每个值的版本不超过一个版本。通过此架构使用 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));
将行写入表
循环遍历一系列问候语字符串,从而为该表创建一些新行。
在每次迭代中,使用 SingleRowMutation
来定义行并为其分配行键和值。然后调用 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;
}
创建过滤条件
在读取您写入的数据之前,请使用 Filter::ColumnRangeClosed()
创建过滤条件,以限制 Bigtable 返回的数据。此过滤条件指示 Bigtable 仅返回每个值的最新版本,即使表中包含已过期但尚未被垃圾回收移除的单元。
cbt::Filter filter = cbt::Filter::ColumnRangeClosed("family", "c0", "c0");
按行键读取行
调用 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";
扫描所有表行
使用 Table::ReadRows()
从表中读取一系列行。
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";
}
}
删除表
使用 BigtableTableAdminClient::DeleteTable()
删除表格。
google::cloud::Status status = table_admin.DeleteTable(table.table_name());
if (!status.ok()) throw std::runtime_error(status.message());
综合应用
以下为不包含注释的完整示例。
#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];
namespace cbt = ::google::cloud::bigtable;
namespace cbta = ::google::cloud::bigtable_admin;
using ::google::cloud::StatusOr;
cbta::BigtableTableAdminClient table_admin(
cbta::MakeBigtableTableAdminConnection());
cbt::Table table(cbt::MakeDataConnection(),
cbt::TableResource(project_id, instance_id, table_id));
google::bigtable::admin::v2::Table t;
auto& families = *t.mutable_column_families();
families["family"].mutable_gc_rule()->set_max_num_versions(1);
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));
std::vector<std::string> greetings{"Hello World!", "Hello Cloud Bigtable!",
"Hello C++!"};
int i = 0;
for (auto const& greeting : greetings) {
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");
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";
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";
}
}
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";
::google::cloud::LogSink::Instance().Flush();
return 1;
}