Skip to content

Martini Google Cloud Bigtable Functions

Overview

Martini Google Cloud Bigtable Functions (BigtableMethods) let your workflows and services create and manage Bigtable tables and column families, read and mutate rows, and stream large result sets, without hand-rolling Google Cloud Bigtable client code.

These functions cover the full lifecycle of working with a Bigtable table — creating it with column families and optional split keys, reading and writing individual rows, streaming large scans and batch mutations through Martini cursors, and dropping rows, families, or the table itself — while returning a mix of data models, booleans, cursors, and void results depending on the function.

What You Will Learn

  • How to create, inspect, and delete a Bigtable table with createTable, getTable, listTables, and deleteTable
  • How to add, update, and drop column families with addFamily, updateFamily, and dropFamily, using the mapGCRule parameter
  • How to read a single row with readRow, check whether a row exists with exists, and stream a large row scan with openRowInputCursor
  • How to write a single row with mutateRow, delete a single row with deleteRow, and batch-mutate many rows with openBatchMutateOutputCursor
  • How checkAndMutateRow and readModifyWriteRow apply conditional and atomic row updates

When To Use This

Use Bigtable Functions when you need to:

  • Provision a new Bigtable table with one or more column families and an optional garbage-collection rule per family
  • Read, filter, or check the existence of a single row without scanning the whole table
  • Stream a large row scan or a large batch of row mutations without loading the entire result into memory
  • Apply a conditional update to a row, or atomically append/increment a row's cell values on the server
  • Delete a single row, a range of rows by key prefix, all rows in a table, or the table itself

Prerequisites


Managing Tables and Column Families

Every Bigtable Function call starts with a connectionName — the name of the Bigtable connection registered in Martini Runtime. Most table and family functions also take a required tableId identifying the target table. listTables only requires connectionName because it enumerates all tables on the connection.

Creating and Inspecting Tables

createTable creates a new table together with one or more column families in a single call. Configure each family's name and garbage-collection rule using the mapGCRule parameter, an array of MapGCRule entries — even when you only need a single family, supply it as a one-entry list.

Parameter Required Description
connectionName Yes The name of the Bigtable connection registered in Martini Runtime.
tableId Yes The ID of the table to create.
mapGCRule No An array of column family names paired with a garbage-collection (GCRule) rule, used to create each family on the new table.
splitKey No An optional list of row keys used to pre-split the table into multiple tablets at creation time; improves write distribution for known key ranges.
1
createTable(connectionName: 'bigtableDb', tableId: 'products', mapGCRule: [[familyId: 'cf1', gcRule: maxVersionsRule]], splitKey: null)

createTable returns a data model describing the created table, including its tableId and configured column families. Check this returned model against the family names and garbage-collection rules you requested to confirm the table was provisioned as expected before your workflow or service starts writing to it.

getTable returns the same kind of table data model for an existing table, which you can inspect the same way to confirm a table's current column families before reading from or writing to it. listTables returns the IDs of every table configured on the connection, which you can use to check that an expected table exists before targeting it by name, or to loop over every table on a connection for a maintenance task.

Adding, Updating, and Dropping Column Families

addFamily and updateFamily share the same mapGCRule parameter as createTable — an array of column family names paired with a GCRule — so you can add new families or change the garbage-collection rule of existing ones without recreating the table. dropFamily removes one or more families by name.

Function Parameter Required Description
addFamily(connectionName, tableId, mapGCRule) mapGCRule No An array of column family names paired with a GCRule, used to create each new family on the table.
updateFamily(connectionName, tableId, mapGCRule) mapGCRule No An array of column family names paired with a GCRule, used to update each existing family's garbage-collection rule.
dropFamily(connectionName, tableId, familyId) familyId No A list of column family names to drop from the table.

All three methods return a data model describing the updated table.

1
addFamily(connectionName: 'bigtableDb', tableId: 'products', mapGCRule: [[familyId: 'cf2', gcRule: maxAgeRule]])

Check the returned table data model's family list to confirm the new or updated family and its garbage-collection rule were applied before your workflow or service starts writing data into that family.

Deleting Rows, Families, and Tables

Use these functions to remove data at increasing levels of granularity, from a range of rows up to the whole table.

Function Description
dropRowRange(connectionName, tableId, rowKeyPrefix) Drops every row whose key starts with rowKeyPrefix.
dropAllRows(connectionName, tableId) Drops every row in the table, leaving the table and its column families in place.
deleteTable(connectionName, tableId) Deletes the table itself. Returns true if the table was successfully deleted, false otherwise.

Retiring a table typically involves more than one of these calls in sequence, for example when decommissioning a staging table:

flowchart TD
    A["Drop discontinued rows: dropRowRange(connectionName, tableId, rowKeyPrefix)"] --> B["Delete the now-empty table: deleteTable(connectionName, tableId)"]
    B --> C{"Was the table deleted?"}
    C -->|"true"| D["Continue — the table no longer exists"]
    C -->|"false"| E["Investigate why deletion failed before retrying"]

Check deleteTable's returned boolean before assuming cleanup succeeded — a false result means the table still exists and needs investigation before you retry.

Waiting for Replication Consistency

Use awaitReplication when your workflow needs replication to catch up before continuing with read operations.

Function Description
awaitReplication(connectionName, tableId) Blocks the current thread until replication catches up to the point this method was called, so subsequent reads see the latest writes across all clusters.

Reading and Checking Rows

exists and readRow operate on a single row identified by connectionName, tableId, and rowKey, all of which are required.

Function Return Value Description
exists(connectionName, tableId, rowKey) boolean Returns whether the given row key exists in the table.
readRow(connectionName, tableId, rowKey, condition) data model Synchronously reads a single row, optionally filtered by condition.

readRow's condition parameter (shown as condition in Martini Designer's mapper) applies a Bigtable row filter, so you can restrict which columns or cell versions are returned instead of always reading the full row. Leave condition null to read the entire row.

1
readRow(connectionName: 'bigtableDb', tableId: 'products', rowKey: 'product-42', condition: latestVersionFilter)

readRow returns a data model containing the row data, or an empty row data model if rowKey does not exist. Check whether the returned row model has any cells before mapping its values further downstream, so a missing row doesn't cause a null-value error later in the workflow or service.

Streaming Large Row Scans with openRowInputCursor

openRowInputCursor opens an input cursor for streaming the result of a row query, without accumulating the full result in memory. Use the cursor as the input array of a repeat node in a workflow, or an iterate step in a service. The cursor can only be read once and is automatically closed at the end of the execution.

Parameter Required Description
connectionName Yes The name of the Bigtable connection registered in Martini Runtime.
tableId Yes The ID of the table to query.
rowKey No A specific row key to look up.
prefix No A row key prefix used to filter results; only rows whose key starts with this prefix are returned.
range No A row key range to look up. The start of the range is inclusive and can be left null to represent negative infinity; the end of the range is exclusive and can be left null to represent positive infinity.
condition No A row filter to apply to each row. Only one filter can be set at a time.
limit No The maximum number of rows to return; leave null for no limit.
1
openRowInputCursor(connectionName: 'bigtableDb', tableId: 'products', prefix: 'product-', limit: 500)

openRowInputCursor returns a cursor that can be used to iterate over the query result. Map the returned cursor to the input array of a repeat node or an iterate step so each matching row is processed one at a time, instead of loading every row into memory before processing starts.

Writing and Deleting Rows

Use mutateRow to write a single row, deleteRow to remove a single row, and openBatchMutateOutputCursor to mutate many rows without accumulating them in memory.

Mutating a Single Row with mutateRow

mutateRow mutates a single row in the given table.

Parameter Required Description
connectionName Yes The name of the Bigtable connection registered in Martini Runtime.
tableId Yes The ID of the table.
keyName Yes The name of the row to mutate.
mutation No A data model that describes the sets of mutation to be applied to a single row.
1
mutateRow(connectionName: 'bigtableDb', tableId: 'products', keyName: 'product-42', mutation: [[familyId: 'cf1', column: 'price', value: '19.99']])

mutateRow returns void; there's no result to inspect. Instead, if the next step in your workflow or service depends on the write having happened — for example, before reading the row back — sequence that read after the call to mutateRow completes.

Deleting a Single Row with deleteRow

deleteRow deletes a single row from a Bigtable table by its row key. Use it instead of openBatchMutateOutputCursor when you only need to remove one record.

Parameter Required Description
connectionName Yes The name of the Bigtable connection registered in Martini Runtime.
tableId Yes The ID of the table from which the row will be deleted.
rowKey Yes The key of the row to delete.
1
deleteRow(connectionName: 'bigtableDb', tableId: 'products', rowKey: 'product-42')

deleteRow returns void and throws IOException if the delete operation fails or the connection cannot be established. Catch that exception in your workflow or service if it needs to continue even when a delete fails, for example to log the failed rowKey for a retry later.

Batch-Mutating Rows with openBatchMutateOutputCursor

openBatchMutateOutputCursor opens an output cursor for mutating rows in a table by batch, without accumulating all the mutations in memory. Use the cursor as the output array of a repeat node in a workflow, or an iterate step in a service. Mutations mapped to the cursor are performed when batchSize is reached or at the end of the iteration.

Parameter Required Description
connectionName Yes The name of the Bigtable connection registered in Martini Runtime.
tableId Yes The ID of the table.
batchSize No How many write models to cache before sending them to Bigtable. Defaults to 10000.
closeClient Yes Whether to close the client once the cursor has been closed. Defaults to false.
1
openBatchMutateOutputCursor(connectionName: 'bigtableDb', tableId: 'products', batchSize: 500, closeClient: true)

openBatchMutateOutputCursor returns an output cursor for mutating rows in a table by batch. Map the returned cursor to the output array of a repeat node or an iterate step, writing one mutation model per iteration; Martini sends the accumulated mutations to Bigtable once batchSize mutations have been written, or when the iteration ends.

Applying Conditional and Atomic Row Updates

checkAndMutateRow and readModifyWriteRow cover row updates that need to happen conditionally or atomically on the server, instead of a straightforward mutateRow call.

checkAndMutateRow is a convenience method to synchronously mutate a row atomically based on the output of a filter:

Parameter Required Description
connectionName Yes The name of the Bigtable connection registered in Martini Runtime.
tableId Yes The ID of the table.
rowKey Yes The name of the row.
condition No The filter to be applied to the contents of the specified row.
then No Changes to be atomically applied to the specified row if condition yields at least one cell when applied to the row.
otherwise No Changes to be atomically applied to the specified row if condition does not yield any cells when applied to the row.
flowchart TD
    A["checkAndMutateRow(connectionName, tableId, rowKey, condition, then, otherwise)"] --> B{"Did condition match a cell in the row?"}
    B -->|"Yes"| C["Apply the mutations in then"]
    B -->|"No"| D["Apply the mutations in otherwise"]
    C --> E["Returns true"]
    D --> F["Returns false"]

Branch on checkAndMutateRow's returned boolean in your workflow or service if you need to react differently depending on whether then or otherwise was applied — for example, to log which branch ran.

Convenience method that synchronously modifies a row atomically on the server.

For example, use readModifyWriteRow to atomically append to or increment an existing cell value:

Parameter Required Description
connectionName Yes The name of the Bigtable connection registered in Martini Runtime.
tableId Yes The ID of the table.
rowKey Yes The name of the row.
readModifyWriteRowRequest No A data model describing the read-modify-write request to apply.
1
readModifyWriteRow(connectionName: 'bigtableDb', tableId: 'products', rowKey: 'product-42', readModifyWriteRowRequest: [[familyId: 'cf1', column: 'views', incrementAmount: 1]])

readModifyWriteRow returns a data model containing the updated row data, reflecting the value after the server-side append or increment. Read the relevant cell from the returned row model if the next step in your workflow or service needs the new value, instead of re-reading the row with a separate readRow call.

Helpful Resources