blob: 5533dd8d32c29b1e439e28b9f00e4e34e5bb088c [file] [log] [blame]
// 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.
package datastore_test
import (
"fmt"
"log"
"time"
"cloud.google.com/go/datastore"
"golang.org/x/net/context"
)
type Task struct {
Type string
Done bool
Priority int
Description string `datastore:",noindex"`
PercentComplete float64
Created time.Time
Tags []string
Collaborators []string
}
func ExampleNewIncompleteKey() {
ctx := context.Background()
// [START incomplete_key]
taskKey := datastore.NewIncompleteKey(ctx, "Task", nil)
// [END incomplete_key]
_ = taskKey // Use the task key for datastore operations.
}
func ExampleNewKey() {
ctx := context.Background()
// [START named_key]
taskKey := datastore.NewKey(ctx, "Task", "sampletask", 0, nil)
// [END named_key]
_ = taskKey // Use the task key for datastore operations.
}
func ExampleNewKey_withParent() {
ctx := context.Background()
// [START key_with_parent]
parentKey := datastore.NewKey(ctx, "TaskList", "default", 0, nil)
taskKey := datastore.NewKey(ctx, "Task", "sampleTask", 0, parentKey)
// [END key_with_parent]
_ = taskKey // Use the task key for datastore operations.
}
func ExampleNewKey_withMultipleParents() {
ctx := context.Background()
// [START key_with_multilevel_parent]
userKey := datastore.NewKey(ctx, "User", "alice", 0, nil)
parentKey := datastore.NewKey(ctx, "TaskList", "default", 0, userKey)
taskKey := datastore.NewKey(ctx, "Task", "sampleTask", 0, parentKey)
// [END key_with_multilevel_parent]
_ = taskKey // Use the task key for datastore operations.
}
func ExampleClient_Put() {
ctx := context.Background()
client, _ := datastore.NewClient(ctx, "my-proj")
// [START entity_with_parent]
parentKey := datastore.NewKey(ctx, "TaskList", "default", 0, nil)
key := datastore.NewIncompleteKey(ctx, "Task", parentKey)
task := Task{
Type: "Personal",
Done: false,
Priority: 4,
Description: "Learn Cloud Datastore",
}
// A complete key is assigned to the entity when it is Put.
var err error
key, err = client.Put(ctx, key, &task)
// [END entity_with_parent]
_ = err // Make sure you check err.
}
func Example_properties() {
// [START properties]
type Task struct {
Type string
Done bool
Priority int
Description string `datastore:",noindex"`
PercentComplete float64
Created time.Time
}
task := &Task{
Type: "Personal",
Done: false,
Priority: 4,
Description: "Learn Cloud Datastore",
PercentComplete: 10.0,
Created: time.Now(),
}
// [END properties]
_ = task // Use the task in a datastore Put operation.
}
func Example_sliceProperties() {
// [START array_value]
type Task struct {
Tags []string
Collaborators []string
}
task := &Task{
Tags: []string{"fun", "programming"},
Collaborators: []string{"alice", "bob"},
}
// [END array_value]
_ = task // Use the task in a datastore Put operation.
}
func Example_basicEntity() {
// [START basic_entity]
type Task struct {
Type string
Done bool
Priority float64
Description string `datastore:",noindex"`
PercentComplete float64
Created time.Time
}
task := &Task{
Type: "Personal",
Done: false,
Priority: 4,
Description: "Learn Cloud Datastore",
PercentComplete: 10.0,
Created: time.Now(),
}
// [END basic_entity]
_ = task // Use the task in a datastore Put operation.
}
func ExampleClient_Put_upsert() {
ctx := context.Background()
client, _ := datastore.NewClient(ctx, "my-proj")
task := &Task{} // Populated with appropriate data.
key := datastore.NewIncompleteKey(ctx, "Task", nil)
// [START upsert]
key, err := client.Put(ctx, key, task)
// [END upsert]
_ = err // Make sure you check err.
_ = key // key is the complete key for the newly stored task
}
func ExampleTransaction_insert() {
ctx := context.Background()
client, _ := datastore.NewClient(ctx, "my-proj")
task := &Task{} // Populated with appropriate data.
taskKey := datastore.NewKey(ctx, "Task", "sampleTask", 0, nil)
// [START insert]
tx, err := client.NewTransaction(ctx)
if err != nil {
log.Fatalf("client.NewTransaction: %v", err)
}
// We first check that there is no entity stored with the given key.
if err := tx.Get(taskKey, nil); err != datastore.ErrNoSuchEntity {
log.Fatalf("tx.Get returned err %v, want ErrNoSuchEntity", err)
}
if _, err := tx.Put(taskKey, task); err != nil {
log.Fatalf("tx.Put: %v", err)
}
if _, err := tx.Commit(); err != nil {
log.Fatalf("tx.Commit: %v", err)
}
// [END insert]
}
func ExampleClient_Get() {
ctx := context.Background()
client, _ := datastore.NewClient(ctx, "my-proj")
taskKey := datastore.NewKey(ctx, "Task", "sampleTask", 0, nil)
// [START lookup]
var task Task
err := client.Get(ctx, taskKey, &task)
// [END lookup]
_ = err // Make sure you check err.
}
func ExampleTransaction_update() {
ctx := context.Background()
client, _ := datastore.NewClient(ctx, "my-proj")
taskKey := datastore.NewKey(ctx, "Task", "sampleTask", 0, nil)
// [START update]
tx, err := client.NewTransaction(ctx)
if err != nil {
log.Fatalf("client.NewTransaction: %v", err)
}
var task Task
if err := tx.Get(taskKey, &task); err != nil {
log.Fatalf("tx.Get: %v", err)
}
task.Priority = 5
if _, err := tx.Put(taskKey, task); err != nil {
log.Fatalf("tx.Put: %v", err)
}
if _, err := tx.Commit(); err != nil {
log.Fatalf("tx.Commit: %v", err)
}
// [END update]
}
func ExampleClient_Delete() {
ctx := context.Background()
client, _ := datastore.NewClient(ctx, "my-proj")
key := datastore.NewKey(ctx, "Task", "sampletask", 0, nil)
// [START delete]
err := client.Delete(ctx, key)
// [END delete]
_ = err // Make sure you check err.
}
func ExampleClient_PutMulti() {
ctx := context.Background()
client, _ := datastore.NewClient(ctx, "my-proj")
// [START batch_upsert]
tasks := []*Task{
{
Type: "Personal",
Done: false,
Priority: 4,
Description: "Learn Cloud Datastore",
},
{
Type: "Personal",
Done: false,
Priority: 5,
Description: "Integrate Cloud Datastore",
},
}
keys := []*datastore.Key{
datastore.NewIncompleteKey(ctx, "Task", nil),
datastore.NewIncompleteKey(ctx, "Task", nil),
}
keys, err := client.PutMulti(ctx, keys, tasks)
// [END batch_upsert]
_ = err // Make sure you check err.
_ = keys // keys now has the complete keys for the newly stored tasks.
}
func ExampleClient_GetMulti() {
ctx := context.Background()
client, _ := datastore.NewClient(ctx, "my-proj")
var taskKeys []*datastore.Key // Populated with incomplete keys.
// [START batch_lookup]
var tasks []*Task
err := client.GetMulti(ctx, taskKeys, &tasks)
// [END batch_lookup]
_ = err // Make sure you check err.
}
func ExampleClient_DeleteMulti() {
ctx := context.Background()
client, _ := datastore.NewClient(ctx, "my-proj")
var taskKeys []*datastore.Key // Populated with incomplete keys.
// [START batch_delete]
err := client.DeleteMulti(ctx, taskKeys)
// [END batch_delete]
_ = err // Make sure you check err.
}
func ExampleQuery_basic() {
ctx := context.Background()
client, _ := datastore.NewClient(ctx, "my-proj")
// [START basic_query]
query := datastore.NewQuery("Task").
Filter("Done =", false).
Filter("Priority >=", 4).
Order("-Priority")
// [END basic_query]
// [START run_query]
it := client.Run(ctx, query)
for {
var task Task
_, err := it.Next(&task)
if err == datastore.Done {
break
}
if err != nil {
log.Fatalf("Error fetching next task: %v", err)
}
fmt.Printf("Task %q, Priority %d\n", task.Description, task.Priority)
}
// [END run_query]
}
func ExampleQuery_propertyFilter() {
// [START property_filter]
query := datastore.NewQuery("Task").Filter("Done =", false)
// [END property_filter]
_ = query // Use client.Run or client.GetAll to execute the query.
}
func ExampleQuery_compositeFilter() {
// [START composite_filter]
query := datastore.NewQuery("Task").Filter("Done =", false).Filter("Priority =", 4)
// [END composite_filter]
_ = query // Use client.Run or client.GetAll to execute the query.
}
func ExampleQuery_keyFilter() {
ctx := context.Background()
// [START key_filter]
key := datastore.NewKey(ctx, "Task", "someTask", 0, nil)
query := datastore.NewQuery("Task").Filter("__key__ >", key)
// [END key_filter]
_ = query // Use client.Run or client.GetAll to execute the query.
}
func ExampleQuery_sortAscending() {
// [START ascending_sort]
query := datastore.NewQuery("Task").Order("created")
// [END ascending_sort]
_ = query // Use client.Run or client.GetAll to execute the query.
}
func ExampleQuery_sortDescending() {
// [START descending_sort]
query := datastore.NewQuery("Task").Order("-created")
// [END descending_sort]
_ = query // Use client.Run or client.GetAll to execute the query.
}
func ExampleQuery_sortMulti() {
// [START multi_sort]
query := datastore.NewQuery("Task").Order("-priority").Order("created")
// [END multi_sort]
_ = query // Use client.Run or client.GetAll to execute the query.
}
func ExampleQuery_kindless() {
var lastSeenKey *datastore.Key
// [START kindless_query]
query := datastore.NewQuery("").Filter("__key__ >", lastSeenKey)
// [END kindless_query]
_ = query // Use client.Run or client.GetAll to execute the query.
}
func ExampleQuery_Ancestor() {
ctx := context.Background()
// [START ancestor_query]
ancestor := datastore.NewKey(ctx, "TaskList", "default", 0, nil)
query := datastore.NewQuery("Task").Ancestor(ancestor)
// [END ancestor_query]
_ = query // Use client.Run or client.GetAll to execute the query.
}
func ExampleQuery_Project() {
ctx := context.Background()
client, _ := datastore.NewClient(ctx, "my-proj")
// [START projection_query]
query := datastore.NewQuery("Task").Project("Priority", "PercentComplete")
// [END projection_query]
// [START run_query_projection]
var priorities []int
var percents []float64
it := client.Run(ctx, query)
for {
var task Task
if _, err := it.Next(&task); err == datastore.Done {
break
} else if err != nil {
log.Fatal(err)
}
priorities = append(priorities, task.Priority)
percents = append(percents, task.PercentComplete)
}
// [END run_query_projection]
}
func ExampleQuery_KeysOnly() {
ctx := context.Background()
client, _ := datastore.NewClient(ctx, "my-proj")
// [START keys_only_query]
query := datastore.NewQuery("Task").KeysOnly()
// [END keys_only_query]
// [START run_keys_only_query]
keys, err := client.GetAll(ctx, query, nil)
// [END run_keys_only_query]
_ = err // Make sure you check err.
_ = keys // Keys contains keys for all stored tasks.
}
func ExampleQuery_Distinct() {
// [START distinct_query]
query := datastore.NewQuery("Task").
Project("Priority", "PercentComplete").
Distinct().
Order("Type").Order("Priority")
// [END distinct_query]
_ = query // Use client.Run or client.GetAll to execute the query.
// [START distinct_on_query]
// DISTINCT ON not supported in Go API
// [END distinct_on_query]
}
func ExampleQuery_Filter_arrayInequality() {
// [START array_value_inequality_range]
query := datastore.NewQuery("Task").
Filter("Tag >", "learn").
Filter("Tag <", "math")
// [END array_value_inequality_range]
_ = query // Use client.Run or client.GetAll to execute the query.
}
func ExampleQuery_Filter_arrayEquality() {
// [START array_value_equality]
query := datastore.NewQuery("Task").
Filter("Tag =", "fun").
Filter("Tag =", "programming")
// [END array_value_equality]
_ = query // Use client.Run or client.GetAll to execute the query.
}
func ExampleQuery_Filter_inequality() {
// [START inequality_range]
query := datastore.NewQuery("Task").
Filter("Created >", time.Date(1990, 1, 1, 0, 0, 0, 0, time.UTC)).
Filter("Created <", time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC))
// [END inequality_range]
_ = query // Use client.Run or client.GetAll to execute the query.
}
func ExampleQuery_Filter_invalidInequality() {
// [START inequality_invalid]
query := datastore.NewQuery("Task").
Filter("Created >", time.Date(1990, 1, 1, 0, 0, 0, 0, time.UTC)).
Filter("Priority >", 3)
// [END inequality_invalid]
_ = query // The query is invalid.
}
func ExampleQuery_Filter_mixed() {
// [START equal_and_inequality_range]
query := datastore.NewQuery("Task").
Filter("Priority =", 4).
Filter("Done =", false).
Filter("Created >", time.Date(1990, 1, 1, 0, 0, 0, 0, time.UTC)).
Filter("Created <", time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC))
// [END equal_and_inequality_range]
_ = query // Use client.Run or client.GetAll to execute the query.
}
func ExampleQuery_inequalitySort() {
// [START inequality_sort]
query := datastore.NewQuery("Task").
Filter("Priority >", 3).
Order("Priority").
Order("Created")
// [END inequality_sort]
_ = query // Use client.Run or client.GetAll to execute the query.
}
func ExampleQuery_invalidInequalitySortA() {
// [START inequality_sort_invalid_not_same]
query := datastore.NewQuery("Task").
Filter("Priority >", 3).
Order("Created")
// [END inequality_sort_invalid_not_same]
_ = query // The query is invalid.
}
func ExampleQuery_invalidInequalitySortB() {
// [START inequality_sort_invalid_not_first]
query := datastore.NewQuery("Task").
Filter("Priority >", 3).
Order("Created").
Order("Priority")
// [END inequality_sort_invalid_not_first]
_ = query // The query is invalid.
}
func ExampleQuery_Limit() {
// [START limit]
query := datastore.NewQuery("Task").Limit(5)
// [END limit]
_ = query // Use client.Run or client.GetAll to execute the query.
}
func ExampleIterator_Cursor() {
ctx := context.Background()
client, _ := datastore.NewClient(ctx, "my-proj")
cursorStr := ""
// [START cursor_paging]
const pageSize = 5
query := datastore.NewQuery("Tasks").Limit(pageSize)
if cursorStr != "" {
cursor, err := datastore.DecodeCursor(cursorStr)
if err != nil {
log.Fatalf("Bad cursor %q: %v", cursorStr, err)
}
query = query.Start(cursor)
}
// Read the tasks.
var tasks []Task
var task Task
it := client.Run(ctx, query)
_, err := it.Next(&task)
for err == nil {
tasks = append(tasks, task)
_, err = it.Next(&task)
}
if err != datastore.Done {
log.Fatalf("Failed fetching results: %v", err)
}
// Get the cursor for the next page of results.
nextCursor, err := it.Cursor()
// [END cursor_paging]
_ = err // Check the error.
_ = nextCursor // Use nextCursor.String as the next page's token.
}
func ExampleQuery_EventualConsistency() {
ctx := context.Background()
// [START eventual_consistent_query]
ancestor := datastore.NewKey(ctx, "TaskList", "default", 0, nil)
query := datastore.NewQuery("Task").Ancestor(ancestor).EventualConsistency()
// [END eventual_consistent_query]
_ = query // Use client.Run or client.GetAll to execute the query.
}
func ExampleQuery_unindexed() {
// [START unindexed_property_query]
query := datastore.NewQuery("Tasks").Filter("Description =", "A task description")
// [END unindexed_property_query]
_ = query // Use client.Run or client.GetAll to execute the query.
}
func Example_explodingProperties() {
// [START exploding_properties]
task := &Task{
Tags: []string{"fun", "programming", "learn"},
Collaborators: []string{"alice", "bob", "charlie"},
Created: time.Now(),
}
// [END exploding_properties]
_ = task // Use the task in a datastore Put operation.
}
func Example_Transaction() {
ctx := context.Background()
client, _ := datastore.NewClient(ctx, "my-proj")
var to, from *datastore.Key
// [START transactional_update]
type BankAccount struct {
Balance int
}
const amount = 50
keys := []*datastore.Key{to, from}
tx, err := client.NewTransaction(ctx)
if err != nil {
log.Fatalf("client.NewTransaction: %v", err)
}
accs := make([]BankAccount, 2)
if err := tx.GetMulti(keys, accs); err != nil {
tx.Rollback()
log.Fatalf("tx.GetMulti: %v", err)
}
accs[0].Balance += amount
accs[1].Balance -= amount
if _, err := tx.PutMulti(keys, accs); err != nil {
tx.Rollback()
log.Fatalf("tx.PutMulti: %v", err)
}
if _, err = tx.Commit(); err != nil {
log.Fatalf("tx.Commit: %v", err)
}
// [END transactional_update]
}
func Example_Client_RunInTransaction() {
ctx := context.Background()
client, _ := datastore.NewClient(ctx, "my-proj")
var to, from *datastore.Key
// [START transactional_retry]
type BankAccount struct {
Balance int
}
const amount = 50
_, err := client.RunInTransaction(ctx, func(tx *datastore.Transaction) error {
keys := []*datastore.Key{to, from}
accs := make([]BankAccount, 2)
if err := tx.GetMulti(keys, accs); err != nil {
return err
}
accs[0].Balance += amount
accs[1].Balance -= amount
_, err := tx.PutMulti(keys, accs)
return err
})
// [END transactional_retry]
_ = err // Check error.
}
func ExampleTransaction_getOrCreate() {
ctx := context.Background()
client, _ := datastore.NewClient(ctx, "my-proj")
key := datastore.NewKey(ctx, "Task", "sampletask", 0, nil)
// [START transactional_get_or_create]
_, err := client.RunInTransaction(ctx, func(tx *datastore.Transaction) error {
var task Task
if err := tx.Get(key, &task); err != datastore.ErrNoSuchEntity {
return err
}
_, err := tx.Put(key, &Task{
Type: "Personal",
Done: false,
Priority: 4,
Description: "Learn Cloud Datastore",
})
return err
})
// [END transactional_get_or_create]
_ = err // Check error.
}
func ExampleTransaction_runQuery() {
ctx := context.Background()
client, _ := datastore.NewClient(ctx, "my-proj")
// [START transactional_single_entity_group_read_only]
tx, err := client.NewTransaction(ctx)
if err != nil {
log.Fatalf("client.NewTransaction: %v", err)
}
defer tx.Rollback() // Transaction only used for read.
ancestor := datastore.NewKey(ctx, "TaskList", "default", 0, nil)
query := datastore.NewQuery("Task").Ancestor(ancestor).Transaction(tx)
var tasks []Task
_, err = client.GetAll(ctx, query, &tasks)
// [END transactional_single_entity_group_read_only]
_ = err // Check error.
}
func Example_metadataNamespaces() {
ctx := context.Background()
client, _ := datastore.NewClient(ctx, "my-proj")
// [START namespace_run_query]
const (
startNamespace = "g"
endNamespace = "h"
)
query := datastore.NewQuery("__namespace__").
Filter("__key__ >=", startNamespace).
Filter("__key__ <", endNamespace).
KeysOnly()
keys, err := client.GetAll(ctx, query, nil)
if err != nil {
log.Fatalf("client.GetAll: %v", err)
}
namespaces := make([]string, 0, len(keys))
for _, k := range keys {
namespaces = append(namespaces, k.Name())
}
// [END namespace_run_query]
}
func Example_metadataKinds() {
ctx := context.Background()
client, _ := datastore.NewClient(ctx, "my-proj")
// [START kind_run_query]
query := datastore.NewQuery("__kind__").KeysOnly()
keys, err := client.GetAll(ctx, query, nil)
if err != nil {
log.Fatalf("client.GetAll: %v", err)
}
kinds := make([]string, 0, len(keys))
for _, k := range keys {
kinds = append(kinds, k.Name())
}
// [END kind_run_query]
}
func Example_metadataProperties() {
ctx := context.Background()
client, _ := datastore.NewClient(ctx, "my-proj")
// [START property_run_query]
query := datastore.NewQuery("__property__").KeysOnly()
keys, err := client.GetAll(ctx, query, nil)
if err != nil {
log.Fatalf("client.GetAll: %v", err)
}
props := make(map[string][]string) // Map from kind to slice of properties.
for _, k := range keys {
prop := k.Name()
kind := k.Parent().Name()
props[kind] = append(props[kind], prop)
}
// [END property_run_query]
}
func Example_metadataPropertiesForKind() {
ctx := context.Background()
client, _ := datastore.NewClient(ctx, "my-proj")
// [START property_by_kind_run_query]
kindKey := datastore.NewKey(ctx, "__kind__", "Task", 0, nil)
query := datastore.NewQuery("__property__").Ancestor(kindKey)
type Prop struct {
Repr []string `datastore:"property_representation"`
}
var props []Prop
keys, err := client.GetAll(ctx, query, &props)
// [END property_by_kind_run_query]
_ = err // Check error.
_ = keys // Use keys to find property names, and props for their representations.
}