Deletions of Kiji table cells can be performed both within a MapReduce job and from non-distributed java programs. Both types of programs use KijiTableWriters to delete data.

Point Deletions

You realize one of your frenemies, Renuka Apte (any resemblance to real persons, living or dead, is purely coincidental), has somehow made it to your contact list. To remedy this we will perform a point deletion on the row with Renuka's contact information. To permit deletions from the phonebook, we will create a tool that will let us specify contacts that we want to delete.

DeleteEntry.java

DeleteEntry uses a KijiTableWriter to perform point deletions on a kiji table:

// Connect to the Kiji table and open a writer.
kiji = Kiji.Factory.open(
    KijiURI.newBuilder().withInstanceName(KConstants.DEFAULT_INSTANCE_NAME).build(),
    getConf());
table = kiji.openTable(TABLE_NAME);
writer = table.openTableWriter();

The deletion is then performed by specifying the row ID for the entry, in this case a string of the format firstname,lastname:

// Create a row ID with the first and last name.
EntityId user = table.getEntityId(first + "," + last);

// Delete the row for the specified user.
writer.deleteRow(user);

Running the Example

This example interactively queries the user for the first and last names of the contact to delete. First, verify that the contact entry for Renuka Apte exists in your phonebook table:

$KIJI_HOME/bin/kiji get kiji://.env/default/phonebook --entity-id="['Renuka,Apte']"
Looking up entity: ['Renuka,Apte'] from kiji table: kiji://localhost:2181/default/phonebook/
entity-id=['Renuka,Apte'] [1384235579766] info:firstname
                                 Renuka
entity-id=['Renuka,Apte'] [1384235579766] info:lastname
                                 Apte
entity-id=['Renuka,Apte'] [1384235579766] info:email
                                 ra@wibidata.com
entity-id=['Renuka,Apte'] [1384235579766] info:telephone
                                 415-111-2222
entity-id=['Renuka,Apte'] [1384235579766] info:address
                                 {"addr1": "375 Alabama St", "apt": null, "addr2": null, "city": "SF", "state": "CA", "zip": 94110}

Next, to perform the deletion of this contact using DeleteEntry:

$KIJI_HOME/bin/kiji jar \
    $KIJI_HOME/examples/phonebook/lib/kiji-phonebook-1.1.1.jar \
    org.kiji.examples.phonebook.DeleteEntry
First name: Renuka
Last name: Apte

Verify

To verify that the row has been deleted, run the following command ensuring that the phonebook entry for Renuka does not get printed:

$KIJI_HOME/bin/kiji get kiji://.env/default/phonebook --entity-id="['Renuka,Apte']"
Looking up entity: ['Renuka,Apte'] from kiji table: kiji://localhost:2181/default/phonebook/

Deleting from a MapReduce Job

 

Deprecation Warning

The DeleteEntriesByState MapReduce class refers to classes in the org.kiji.schema.mapreduce package that may be removed in the future. You should use the KijiMR library to manage MapReduce jobs that interoperate with Kiji tables.

You’re tired of all your San Francisco friends bragging about their startups. You’ve decided to clean your phonebook of anyone from the state of California. Since you have so many contacts, it would take too long to use the point deletion tool we created in the previous example. Instead, we will write a MapReduce job to sanitize your phonebook of any California contacts.

DeleteEntriesByState.java

Deletions from within a MapReduce job are also performed using a KijiTableWriter. The DeleteEntriesByState example runs a MapReduce job that reads through the contacts in the phonebook table and deletes any entry that has an address from the specified state.

First, the contact's address is extracted from the row:

public void map(EntityId entityId, KijiRowData row, Context hadoopContext)
    throws IOException {
  // Check that the row has the info:address column.
  // The column names are specified as constants in the Fields.java class.
  if (!row.containsColumn(Fields.INFO_FAMILY, Fields.ADDRESS)) {
    LOG.info("Missing address field in row: " + entityId);
    hadoopContext.getCounter(Counter.MISSING_ADDRESS).increment(1L);
    return;
  }

  final String victimState = hadoopContext.getConfiguration().get(CONF_STATE, "");
  final Address address = row.getMostRecentValue(Fields.INFO_FAMILY, Fields.ADDRESS);

A KijiTableWriter we opened in the setup() method is then used to delete the row if the state matches:

  if (victimState.equals(address.getState().toString())) {
    // Delete the entry.
    mWriter.deleteRow(entityId);
  }
}

Running the Example

You can run the DeleteEntriesByState MapReduce job by running:

$KIJI_HOME/bin/kiji jar \
    $KIJI_HOME/examples/phonebook/lib/kiji-phonebook-1.1.1.jar \
    org.kiji.examples.phonebook.DeleteEntriesByState --state=CA

Verify

To verify that the contacts have been deleted, run the following command ensuring that no phonebook entries from California get printed.

$KIJI_HOME/bin/kiji scan kiji://.env/default/phonebook/derived:state
Scanning kiji table: kiji://localhost:2181/default/phonebook/derived:state/
entity-id=['John,Doe'] [1384236064965] derived:state
                                 DC

Wrapping up

If you started your BentoBox to do this tutorial, now would be a good time to stop it.

bento stop

To learn more about Kiji, check out these other resources: - User Guide - API Docs - Source Code

For information about the Kiji Project and user-to-user support: Sign up for user@kiji.org

Hungry for more? To learn about KijiMR, Kiji's MapReduce integration library, check out the Music recommendation tutorial.