Advanced Reading and Writing Samples

This example is for advanced reading and writing operations on bigtable data client, that illustrates how to:

  • Use ReadModifyWrite to append a string to a value.
  • Use ReadModifyWrite to increment a value.
  • Use the features to simplify reading big-endian values from Cloud Bigtable.
  • Use CheckAndMutate to modify a value only if it exists.

Run 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.

Include the Necessary Headers

The example uses the following headers:

#include "google/cloud/bigtable/table.h"

Connect to the Cloud Bigtable data client endpoint.

  google::cloud::bigtable::Table table(
      google
::cloud::bigtable::MakeDataConnection(),
      google
::cloud::bigtable::TableResource(project_id, instance_id,
                                             table_id
));

Use ReadModifyWrite to increment a value and append a string to a value.

  namespace cbt = ::google::cloud::bigtable;
 
using ::google::cloud::StatusOr;
 
[](cbt::Table table, std::string const& row_key) {
   
StatusOr<cbt::Row> row = table.ReadModifyWriteRow(
        row_key
, cbt::ReadModifyWriteRule::IncrementAmount("fam", "counter", 1),
        cbt
::ReadModifyWriteRule::AppendValue("fam", "list", ";element"));

   
// As the modify in this example is not idempotent, and this example
   
// does not attempt to retry if there is a failure, we simply print
   
// such failures, if any, and otherwise ignore them.
   
if (!row) {
      std
::cout << "Failed to append row: " << row.status().message() << "\n";
     
return;
   
}
   
// Print the contents of the row
    std
::cout << row->row_key() << "\n";
   
for (auto const& cell : row->cells()) {
      std
::cout << "    " << cell.family_name() << ":"
               
<< cell.column_qualifier() << " = <";
     
if (cell.column_qualifier() == "counter") {
       
// This example uses "counter" to store 64-bit numbers in big-endian
       
// format, extract them as follows:
        std
::cout << cell.decode_big_endian_integer<std::int64_t>().value();
     
} else {
        std
::cout << cell.value();
     
}
      std
::cout << ">\n";
   
}
 
}

Use the features to simplify reading big-endian values from Cloud Bigtable.

  namespace cbt = ::google::cloud::bigtable;
 
using ::google::cloud::StatusOr;
 
[](google::cloud::bigtable::Table table, std::string const& row_key) {
   
StatusOr<std::pair<bool, cbt::Row>> tuple = table.ReadRow(
        row_key
, cbt::Filter::ColumnName("stats_summary", "os_build"));
   
if (!tuple) throw std::move(tuple).status();
   
if (!tuple->first) {
      std
::cout << "Row " << row_key << " not found\n";
     
return;
   
}
   
PrintRow(tuple->second);
 
}

Use CheckAndMutate to modify a cell if it has a value.

  namespace cbt = ::google::cloud::bigtable;
 
using ::google::cloud::StatusOr;
 
[](cbt::Table table, std::string const& row_key) {
   
// Check if the latest value of the flip-flop column is "on".
    cbt
::Filter predicate = cbt::Filter::Chain(
        cbt
::Filter::ColumnRangeClosed("fam", "flip-flop", "flip-flop"),
        cbt
::Filter::Latest(1), cbt::Filter::ValueRegex("on"));
   
// If the predicate matches, change the latest value to "off", otherwise,
   
// change the latest value to "on".  Modify the "flop-flip" column at the
   
// same time.
   
StatusOr<cbt::MutationBranch> branch =
        table
.CheckAndMutateRow(row_key, std::move(predicate),
                               
{cbt::SetCell("fam", "flip-flop", "off"),
                                 cbt
::SetCell("fam", "flop-flip", "on")},
                               
{cbt::SetCell("fam", "flip-flop", "on"),
                                 cbt
::SetCell("fam", "flop-flip", "off")});

   
if (!branch) throw std::move(branch).status();
   
if (*branch == cbt::MutationBranch::kPredicateMatched) {
      std
::cout << "The predicate was matched\n";
   
} else {
      std
::cout << "The predicate was not matched\n";
   
}
 
}

Use CheckAndMutate to modify a cell if another cell exists.

  namespace cbt = ::google::cloud::bigtable;
 
using ::google::cloud::StatusOr;
 
[](cbt::Table table, std::string const& row_key) {
   
// Check if the latest value of the "test-column" column is present,
   
// regardless of its value.
    cbt
::Filter predicate = cbt::Filter::Chain(
        cbt
::Filter::ColumnRangeClosed("fam", "test-column", "test-column"),
        cbt
::Filter::Latest(1));
   
// If the predicate matches, do nothing, otherwise set the
   
// "had-test-column" to "false":
   
StatusOr<cbt::MutationBranch> branch = table.CheckAndMutateRow(
        row_key
, std::move(predicate), {},
       
{cbt::SetCell("fam", "had-test-column", "false")});

   
if (!branch) throw std::move(branch).status();
   
if (*branch == cbt::MutationBranch::kPredicateMatched) {
      std
::cout << "The predicate was matched\n";
   
} else {
      std
::cout << "The predicate was not matched\n";
   
}
 
}