Skip to content
Advertisement

BigTable ReadModifyWriteRow Support for Mapping Function

I am aware that BigTable supports operations append and increment using ReadModifyWriteRow requests, but I’m wondering if there is support or an alternative way to use more generic mapping functions where the value from the cell can be accessed and modified within some sort of closure? For instance, bitwise ANDing a long value in a cell:

Function<Long, Long> modifyFunc = f -> f & 10L;

ReadModifyWriteRow
  .create("tableName", "rowKey")
  .apply("family", "qualifier", modifyFunc);

Advertisement

Answer

Doing a mapping like this is not supported by Bigtable, so here is an option you could try. This will only work with single cluster instances due to consistency required for it.

You could add a column to keep track of row version (in addition to the existing row versions) and then you can read the data and version, modify it in memory and then do a checkAndMutate with the version and new value. Something like this:

Row row = dataClient.readRow(tableId, rowkey);
ArrayList<RowCell> cells = row.getCells();

// Get the value and timestamp/version from the cell you are targetting.
RowCell cell = cells.get(...);
long version = cell.getTimestamp();
ByteString value = cell.getValue();

// Do your mapping to the new value.
ByteString newValue = ...;

Mutation mutation =
    Mutation.create().setCell(COLUMN_FAMILY_NAME, COLUMN_NAME, timestamp, newValue);

// Filter on a column that tracks the version to do validation.
Filter filter =
    FILTERS
        .chain()
        .filter(FILTERS.family().exactMatch(COLUMN_FAMILY_NAME))
        .filter(FILTERS.qualifier().exactMatch(VERSION_COLUMN))
        .filter(FILTERS.value().exactMatch(version));

ConditionalRowMutation conditionalRowMutation =
    ConditionalRowMutation.create(tableId, rowkey).condition(filter).then(mutation);

boolean success = dataClient.checkAndMutateRow(conditionalRowMutation);
Advertisement