| // Copyright 2016 Google Inc. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| // Hello world is a sample program demonstrating use of the Bigtable client |
| // library to perform basic CRUD operations |
| package main |
| |
| import ( |
| "flag" |
| "fmt" |
| "log" |
| |
| "cloud.google.com/go/bigtable" |
| "golang.org/x/net/context" |
| ) |
| |
| // User-provided constants. |
| const ( |
| tableName = "Hello-Bigtable" |
| columnFamilyName = "cf1" |
| columnName = "greeting" |
| ) |
| |
| var greetings = []string{"Hello World!", "Hello Cloud Bigtable!", "Hello golang!"} |
| |
| // sliceContains reports whether the provided string is present in the given slice of strings. |
| func sliceContains(list []string, target string) bool { |
| for _, s := range list { |
| if s == target { |
| return true |
| } |
| } |
| return false |
| } |
| |
| 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) |
| } |
| } |