Code snippets for using a HBase golang client

April 5th, 2024


Getting started with github.com/tsuna/gohbase was a bit confusing, leaving behind some useful snippets for the Joe Schmoe.

Installation

Installation on macOS was easy

brew install hbase
brew services start hbase

Admin

DDL is separated out from other statements. HBase has the idea of “column families” which are the groups of columns: {column-family: {column: value}}. Column families have some co-location benefit, in a distributed HBase scenario. From what I can tell, the columns created aren’t really enforced. I also never figured out what the point of the “value” was, despite googling around quite a bit.

Create table

admin := gohbase.NewAdminClient("localhost")

// Create Table
family := map[string]map[string]string{"cf1": {}, "cf2": {}}
createTableRequest := hrpc.NewCreateTable(ctx, []byte("t1"), family, func(ct *hrpc.CreateTable) {})
err := admin.CreateTable(createTableRequest)
if err != nil {
    panic(err)
}

Drop table

To drop a table, you need to disable it first.

disableTableReq := hrpc.NewDisableTable(ctx, []byte("t1"))
if err := admin.DisableTable(disableTableReq); err != nil {
    panic(err)
}
deleteTableReq := hrpc.NewDeleteTable(ctx, []byte("t1"))
if err := admin.DeleteTable(deleteTableReq); err != nil {
    panic(err)
}

Application

Inserting

You can just make up columns.

client := gohbase.NewClient("localhost")

values := map[string]map[string][]byte{"cf1": {"c1": []byte("Hello, world!")}}
putRequest, err := hrpc.NewPutStr(ctx, "t1", "k1", values)
if err != nil {
    panic(err)
}
_, err := client.Put(putRequest)
if err != nil {
    panic(err)
}

Read

Get

getRequest, err := hrpc.NewGetStr(ctx, "t1", "k2", hrpc.Families(family))
if err != nil {
    panic(err)
}

getRsp, err := client.Get(getRequest)
if err != nil {
    panic(err)
}
if getRsp == nil {
    panic(errors.New("Get response is nil"))
}

for _, cell := range getRsp.Cells {
    fmt.Println("key", string(cell.Row), "value", string(cell.Value))
}

Scan

HBase organizes rows lexographically, so scanning nearby rows is very efficient (versus random filters).

scanRequest, err := hrpc.NewScanRange(ctx, []byte("t1"), []byte("k1"), []byte("k4"), hrpc.Families(family))
if err != nil {
    panic(err)
}
client.Get(scanRequest)
scanRsp := client.Scan(scanRequest)
for {
    r, err := scanRsp.Next()
    if err != nil {
        if err == io.EOF {
            break
        }
        panic(err)
    }
    for _, cell := range r.Cells {
        fmt.Println("key", string(cell.Row), "value", string(cell.Value))
    }
}