// Copyright 2014 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. package datastore_test import ( "fmt" "log" "time" "cloud.google.com/go/datastore" "golang.org/x/net/context" "google.golang.org/api/iterator" ) func ExampleNewClient() { ctx := context.Background() client, err := datastore.NewClient(ctx, "project-id") if err != nil { // TODO: Handle error. } _ = client // TODO: Use client. } func ExampleClient_Get() { ctx := context.Background() client, err := datastore.NewClient(ctx, "project-id") if err != nil { // TODO: Handle error. } type Article struct { Title string Description string Body string `datastore:",noindex"` Author *datastore.Key PublishedAt time.Time } key := datastore.NameKey("Article", "articled1", nil) article := &Article{} if err := client.Get(ctx, key, article); err != nil { // TODO: Handle error. } } func ExampleClient_Put() { ctx := context.Background() client, err := datastore.NewClient(ctx, "project-id") if err != nil { // TODO: Handle error. } type Article struct { Title string Description string Body string `datastore:",noindex"` Author *datastore.Key PublishedAt time.Time } newKey := datastore.IncompleteKey("Article", nil) _, err = client.Put(ctx, newKey, &Article{ Title: "The title of the article", Description: "The description of the article...", Body: "...", Author: datastore.NameKey("Author", "jbd", nil), PublishedAt: time.Now(), }) if err != nil { // TODO: Handle error. } } func ExampleClient_Put_flatten() { ctx := context.Background() client, err := datastore.NewClient(ctx, "project-id") if err != nil { log.Fatal(err) } type Animal struct { Name string Type string Breed string } type Human struct { Name string Height int Pet Animal `datastore:",flatten"` } newKey := datastore.IncompleteKey("Human", nil) _, err = client.Put(ctx, newKey, &Human{ Name: "Susan", Height: 67, Pet: Animal{ Name: "Fluffy", Type: "Cat", Breed: "Sphynx", }, }) if err != nil { log.Fatal(err) } } func ExampleClient_Delete() { ctx := context.Background() client, err := datastore.NewClient(ctx, "project-id") if err != nil { // TODO: Handle error. } key := datastore.NameKey("Article", "articled1", nil) if err := client.Delete(ctx, key); err != nil { // TODO: Handle error. } } func ExampleClient_DeleteMulti() { ctx := context.Background() client, err := datastore.NewClient(ctx, "project-id") if err != nil { // TODO: Handle error. } var keys []*datastore.Key for i := 1; i <= 10; i++ { keys = append(keys, datastore.IDKey("Article", int64(i), nil)) } if err := client.DeleteMulti(ctx, keys); err != nil { // TODO: Handle error. } } type Post struct { Title string PublishedAt time.Time Comments int } func ExampleClient_GetMulti() { ctx := context.Background() client, err := datastore.NewClient(ctx, "project-id") if err != nil { // TODO: Handle error. } keys := []*datastore.Key{ datastore.NameKey("Post", "post1", nil), datastore.NameKey("Post", "post2", nil), datastore.NameKey("Post", "post3", nil), } posts := make([]Post, 3) if err := client.GetMulti(ctx, keys, posts); err != nil { // TODO: Handle error. } } func ExampleClient_PutMulti_slice() { ctx := context.Background() client, err := datastore.NewClient(ctx, "project-id") if err != nil { // TODO: Handle error. } keys := []*datastore.Key{ datastore.NameKey("Post", "post1", nil), datastore.NameKey("Post", "post2", nil), } // PutMulti with a Post slice. posts := []*Post{ {Title: "Post 1", PublishedAt: time.Now()}, {Title: "Post 2", PublishedAt: time.Now()}, } if _, err := client.PutMulti(ctx, keys, posts); err != nil { // TODO: Handle error. } } func ExampleClient_PutMulti_interfaceSlice() { ctx := context.Background() client, err := datastore.NewClient(ctx, "project-id") if err != nil { // TODO: Handle error. } keys := []*datastore.Key{ datastore.NameKey("Post", "post1", nil), datastore.NameKey("Post", "post2", nil), } // PutMulti with an empty interface slice. posts := []interface{}{ &Post{Title: "Post 1", PublishedAt: time.Now()}, &Post{Title: "Post 2", PublishedAt: time.Now()}, } if _, err := client.PutMulti(ctx, keys, posts); err != nil { // TODO: Handle error. } } func ExampleNewQuery() { // Query for Post entities. q := datastore.NewQuery("Post") _ = q // TODO: Use the query with Client.Run. } func ExampleNewQuery_options() { // Query to order the posts by the number of comments they have recieved. q := datastore.NewQuery("Post").Order("-Comments") // Start listing from an offset and limit the results. q = q.Offset(20).Limit(10) _ = q // TODO: Use the query. } func ExampleClient_Count() { ctx := context.Background() client, err := datastore.NewClient(ctx, "project-id") if err != nil { // TODO: Handle error. } // Count the number of the post entities. q := datastore.NewQuery("Post") n, err := client.Count(ctx, q) if err != nil { // TODO: Handle error. } fmt.Printf("There are %d posts.", n) } func ExampleClient_Run() { ctx := context.Background() client, err := datastore.NewClient(ctx, "project-id") if err != nil { // TODO: Handle error. } // List the posts published since yesterday. yesterday := time.Now().Add(-24 * time.Hour) q := datastore.NewQuery("Post").Filter("PublishedAt >", yesterday) it := client.Run(ctx, q) _ = it // TODO: iterate using Next. } func ExampleClient_NewTransaction() { ctx := context.Background() client, err := datastore.NewClient(ctx, "project-id") if err != nil { // TODO: Handle error. } const retries = 3 // Increment a counter. // See https://cloud.google.com/appengine/articles/sharding_counters for // a more scalable solution. type Counter struct { Count int } key := datastore.NameKey("counter", "CounterA", nil) var tx *datastore.Transaction for i := 0; i < retries; i++ { tx, err = client.NewTransaction(ctx) if err != nil { break } var c Counter if err = tx.Get(key, &c); err != nil && err != datastore.ErrNoSuchEntity { break } c.Count++ if _, err = tx.Put(key, &c); err != nil { break } // Attempt to commit the transaction. If there's a conflict, try again. if _, err = tx.Commit(); err != datastore.ErrConcurrentTransaction { break } } if err != nil { // TODO: Handle error. } } func ExampleClient_RunInTransaction() { ctx := context.Background() client, err := datastore.NewClient(ctx, "project-id") if err != nil { // TODO: Handle error. } // Increment a counter. // See https://cloud.google.com/appengine/articles/sharding_counters for // a more scalable solution. type Counter struct { Count int } var count int key := datastore.NameKey("Counter", "singleton", nil) _, err = client.RunInTransaction(ctx, func(tx *datastore.Transaction) error { var x Counter if err := tx.Get(key, &x); err != nil && err != datastore.ErrNoSuchEntity { return err } x.Count++ if _, err := tx.Put(key, &x); err != nil { return err } count = x.Count return nil }) if err != nil { // TODO: Handle error. } // The value of count is only valid once the transaction is successful // (RunInTransaction has returned nil). fmt.Printf("Count=%d\n", count) } func ExampleClient_AllocateIDs() { ctx := context.Background() client, err := datastore.NewClient(ctx, "project-id") if err != nil { // TODO: Handle error. } var keys []*datastore.Key for i := 0; i < 10; i++ { keys = append(keys, datastore.IncompleteKey("Article", nil)) } keys, err = client.AllocateIDs(ctx, keys) if err != nil { // TODO: Handle error. } _ = keys // TODO: Use keys. } func ExampleKey_Encode() { key := datastore.IDKey("Article", 1, nil) encoded := key.Encode() fmt.Println(encoded) // Output: EgsKB0FydGljbGUQAQ } func ExampleDecodeKey() { const encoded = "EgsKB0FydGljbGUQAQ" key, err := datastore.DecodeKey(encoded) if err != nil { // TODO: Handle error. } fmt.Println(key) // Output: /Article,1 } func ExampleIDKey() { // Key with numeric ID. k := datastore.IDKey("Article", 1, nil) _ = k // TODO: Use key. } func ExampleNameKey() { // Key with string ID. k := datastore.NameKey("Article", "article8", nil) _ = k // TODO: Use key. } func ExampleIncompleteKey() { k := datastore.IncompleteKey("Article", nil) _ = k // TODO: Use incomplete key. } func ExampleClient_GetAll() { ctx := context.Background() client, err := datastore.NewClient(ctx, "project-id") if err != nil { // TODO: Handle error. } var posts []*Post keys, err := client.GetAll(ctx, datastore.NewQuery("Post"), &posts) for i, key := range keys { fmt.Println(key) fmt.Println(posts[i]) } } func ExampleClient_Mutate() { ctx := context.Background() client, err := datastore.NewClient(ctx, "project-id") if err != nil { // TODO: Handle error. } key1 := datastore.NameKey("Post", "post1", nil) key2 := datastore.NameKey("Post", "post2", nil) key3 := datastore.NameKey("Post", "post3", nil) key4 := datastore.NameKey("Post", "post4", nil) _, err = client.Mutate(ctx, datastore.NewInsert(key1, Post{Title: "Post 1"}), datastore.NewUpsert(key2, Post{Title: "Post 2"}), datastore.NewUpdate(key3, Post{Title: "Post 3"}), datastore.NewDelete(key4)) if err != nil { // TODO: Handle error. } } func ExampleCommit_Key() { ctx := context.Background() client, err := datastore.NewClient(ctx, "") if err != nil { // TODO: Handle error. } var pk1, pk2 *datastore.PendingKey // Create two posts in a single transaction. commit, err := client.RunInTransaction(ctx, func(tx *datastore.Transaction) error { var err error pk1, err = tx.Put(datastore.IncompleteKey("Post", nil), &Post{Title: "Post 1", PublishedAt: time.Now()}) if err != nil { return err } pk2, err = tx.Put(datastore.IncompleteKey("Post", nil), &Post{Title: "Post 2", PublishedAt: time.Now()}) if err != nil { return err } return nil }) if err != nil { // TODO: Handle error. } // Now pk1, pk2 are valid PendingKeys. Let's convert them into real keys // using the Commit object. k1 := commit.Key(pk1) k2 := commit.Key(pk2) fmt.Println(k1, k2) } func ExampleIterator_Next() { ctx := context.Background() client, err := datastore.NewClient(ctx, "project-id") if err != nil { // TODO: Handle error. } it := client.Run(ctx, datastore.NewQuery("Post")) for { var p Post key, err := it.Next(&p) if err == iterator.Done { break } if err != nil { // TODO: Handle error. } fmt.Println(key, p) } } func ExampleIterator_Cursor() { ctx := context.Background() client, err := datastore.NewClient(ctx, "project-id") if err != nil { // TODO: Handle error. } it := client.Run(ctx, datastore.NewQuery("Post")) for { var p Post _, err := it.Next(&p) if err == iterator.Done { break } if err != nil { // TODO: Handle error. } fmt.Println(p) cursor, err := it.Cursor() if err != nil { // TODO: Handle error. } // When printed, a cursor will display as a string that can be passed // to datastore.NewCursor. fmt.Printf("to resume with this post, use cursor %s\n", cursor) } } func ExampleDecodeCursor() { // See Query.Start for a fuller example of DecodeCursor. // getCursor represents a function that returns a cursor from a previous // iteration in string form. cursorString := getCursor() cursor, err := datastore.DecodeCursor(cursorString) if err != nil { // TODO: Handle error. } _ = cursor // TODO: Use the cursor with Query.Start or Query.End. } func getCursor() string { return "" } func ExampleQuery_Start() { // This example demonstrates how to use cursors and Query.Start // to resume an iteration. ctx := context.Background() client, err := datastore.NewClient(ctx, "project-id") if err != nil { // TODO: Handle error. } // getCursor represents a function that returns a cursor from a previous // iteration in string form. cursorString := getCursor() cursor, err := datastore.DecodeCursor(cursorString) if err != nil { // TODO: Handle error. } it := client.Run(ctx, datastore.NewQuery("Post").Start(cursor)) _ = it // TODO: Use iterator. } func ExampleLoadStruct() { type Player struct { User string Score int } // Normally LoadStruct would only be used inside a custom implementation of // PropertyLoadSaver; this is for illustrative purposes only. props := []datastore.Property{ {Name: "User", Value: "Alice"}, {Name: "Score", Value: int64(97)}, } var p Player if err := datastore.LoadStruct(&p, props); err != nil { // TODO: Handle error. } fmt.Println(p) // Output: {Alice 97} } func ExampleSaveStruct() { type Player struct { User string Score int } p := &Player{ User: "Alice", Score: 97, } props, err := datastore.SaveStruct(p) if err != nil { // TODO: Handle error. } fmt.Println(props) // TODO(jba): make this output stable: Output: [{User Alice false} {Score 97 false}] }