func doRead(ctx context.Context, args ...string) { if len(args) < 1 { log.Fatalf("usage: cbt read <table> [args ...]") } tbl := getClient().Open(args[0]) parsed := make(map[string]string) for _, arg := range args[1:] { i := strings.Index(arg, "=") if i < 0 { log.Fatalf("Bad arg %q", arg) } key, val := arg[:i], arg[i+1:] switch key { default: log.Fatalf("Unknown arg key %q", key) case "limit": // Be nicer; we used to support this, but renamed it to "end". log.Fatalf("Unknown arg key %q; did you mean %q?", key, "end") case "start", "end", "prefix", "count": parsed[key] = val } } if (parsed["start"] != "" || parsed["end"] != "") && parsed["prefix"] != "" { log.Fatal(`"start"/"end" may not be mixed with "prefix"`) } var rr bigtable.RowRange if start, end := parsed["start"], parsed["end"]; end != "" { rr = bigtable.NewRange(start, end) } else if start != "" { rr = bigtable.InfiniteRange(start) } if prefix := parsed["prefix"]; prefix != "" { rr = bigtable.PrefixRange(prefix) } var opts []bigtable.ReadOption if count := parsed["count"]; count != "" { n, err := strconv.ParseInt(count, 0, 64) if err != nil { log.Fatalf("Bad count %q: %v", count, err) } opts = append(opts, bigtable.LimitRows(n)) } // TODO(dsymonds): Support filters. err := tbl.ReadRows(ctx, rr, func(r bigtable.Row) bool { printRow(r) return true }, opts...) if err != nil { log.Fatalf("Reading rows: %v", err) } }
func main() { project := flag.String("project", "", "The Google Cloud Platform project ID. Required.") instance := flag.String("instance", "", "The Google Cloud Bigtable instance ID. Required.") flag.Parse() for _, f := range []string{"project", "instance"} { if flag.Lookup(f).Value.String() == "" { log.Fatalf("The %s flag is required.", f) } } ctx := context.Background() // Set up admin client, tables, and column families. // NewAdminClient uses Application Default Credentials to authenticate. adminClient, err := bigtable.NewAdminClient(ctx, *project, *instance) if err != nil { log.Fatalf("Could not create admin client: %v", err) } tables, err := adminClient.Tables(ctx) if err != nil { log.Fatalf("Could not fetch table list: %v", err) } if !sliceContains(tables, tableName) { log.Printf("Creating table %s", tableName) if err := adminClient.CreateTable(ctx, tableName); err != nil { log.Fatalf("Could not create table %s: %v", tableName, err) } } tblInfo, err := adminClient.TableInfo(ctx, tableName) if err != nil { log.Fatalf("Could not read info for table %s: %v", tableName, err) } if !sliceContains(tblInfo.Families, columnFamilyName) { if err := adminClient.CreateColumnFamily(ctx, tableName, columnFamilyName); err != nil { log.Fatalf("Could not create column family %s: %v", columnFamilyName, err) } } // Set up Bigtable data operations client. // NewClient uses Application Default Credentials to authenticate. client, err := bigtable.NewClient(ctx, *project, *instance) if err != nil { log.Fatalf("Could not create data operations client: %v", err) } tbl := client.Open(tableName) muts := make([]*bigtable.Mutation, len(greetings)) rowKeys := make([]string, len(greetings)) log.Printf("Writing greeting rows to table") for i, greeting := range greetings { muts[i] = bigtable.NewMutation() muts[i].Set(columnFamilyName, columnName, bigtable.Now(), []byte(greeting)) // Each row has a unique row key. // // Note: This example uses sequential numeric IDs for simplicity, but // this can result in poor performance in a production application. // Since rows are stored in sorted order by key, sequential keys can // result in poor distribution of operations across nodes. // // For more information about how to design a Bigtable schema for the // best performance, see the documentation: // // https://cloud.google.com/bigtable/docs/schema-design rowKeys[i] = fmt.Sprintf("%s%d", columnName, i) } rowErrs, err := tbl.ApplyBulk(ctx, rowKeys, muts) if err != nil { log.Fatalf("Could not apply bulk row mutation: %v", err) } if rowErrs != nil { for _, rowErr := range rowErrs { log.Printf("Error writing row: %v", rowErr) } log.Fatalf("Could not write some rows") } log.Printf("Getting a single greeting by row key:") row, err := tbl.ReadRow(ctx, rowKeys[0], bigtable.RowFilter(bigtable.ColumnFilter(columnName))) if err != nil { log.Fatalf("Could not read row with key %s: %v", rowKeys[0], err) } log.Printf("\t%s = %s\n", rowKeys[0], string(row[columnFamilyName][0].Value)) log.Printf("Reading all greeting rows:") err = tbl.ReadRows(ctx, bigtable.PrefixRange(columnName), func(row bigtable.Row) bool { item := row[columnFamilyName][0] log.Printf("\t%s = %s\n", item.Row, string(item.Value)) return true }, bigtable.RowFilter(bigtable.ColumnFilter(columnName))) if err = client.Close(); err != nil { log.Fatalf("Could not close data operations client: %v", err) } log.Printf("Deleting the table") if err = adminClient.DeleteTable(ctx, tableName); err != nil { log.Fatalf("Could not delete table %s: %v", tableName, err) } if err = adminClient.Close(); err != nil { log.Fatalf("Could not close admin client: %v", err) } }