datastore

package
v0.0.0-...-246a77c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 24, 2016 License: Apache-2.0 Imports: 19 Imported by: 0

Documentation

Overview

Package datastore contains a Google Cloud Datastore client.

This package is experimental and may make backwards-incompatible changes.

Example (Auth)

TODO(djd): reevaluate this example given new Client config.

// Initialize an authorized context with Google Developers Console
// JSON key. Read the google package examples to learn more about
// different authorization flows you can use.
// http://godoc.org/github.com/tetrafolium/oauth2/google
jsonKey, err := ioutil.ReadFile("/path/to/json/keyfile.json")
if err != nil {
	log.Fatal(err)
}
conf, err := google.JWTConfigFromJSON(
	jsonKey,
	datastore.ScopeDatastore,
	datastore.ScopeUserEmail,
)
if err != nil {
	log.Fatal(err)
}
ctx := context.Background()
client, err := datastore.NewClient(ctx, "project-id", cloud.WithTokenSource(conf.TokenSource(ctx)))
if err != nil {
	log.Fatal(err)
}
// Use the client (see other examples).
return client
Output:

Example (BasicEntity)
package main

import (
	"time"
)

func main() {
	// [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.
}
Output:

Example (ExplodingProperties)
package main

import (
	"time"
)

type Task struct {
	Type            string
	Done            bool
	Priority        int
	Description     string `datastore:",noindex"`
	PercentComplete float64
	Created         time.Time
	Tags            []string
	Collaborators   []string
}

func main() {
	// [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.
}
Output:

Example (MetadataKinds)
package main

import (
	"log"

	"github.com/tetrafolium/gcloud-golang/datastore"
	"golang.org/x/net/context"
)

func main() {
	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]
}
Output:

Example (MetadataNamespaces)
package main

import (
	"log"

	"github.com/tetrafolium/gcloud-golang/datastore"
	"golang.org/x/net/context"
)

func main() {
	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]
}
Output:

Example (MetadataProperties)
package main

import (
	"log"

	"github.com/tetrafolium/gcloud-golang/datastore"
	"golang.org/x/net/context"
)

func main() {
	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]
}
Output:

Example (MetadataPropertiesForKind)
package main

import (
	"github.com/tetrafolium/gcloud-golang/datastore"
	"golang.org/x/net/context"
)

func main() {
	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.
}
Output:

Example (Properties)
package main

import (
	"time"
)

func main() {
	// [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.
}
Output:

Example (SliceProperties)
package main

import ()

func main() {
	// [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.
}
Output:

Index

Examples

Constants

View Source
const (
	// ScopeDatastore grants permissions to view and/or manage datastore entities
	ScopeDatastore = "https://www.googleapis.com/auth/datastore"

	// ScopeUserEmail grants permission to view the user's email address.
	// It is required to access the datastore.
	ScopeUserEmail = "https://www.googleapis.com/auth/userinfo.email"
)

Variables

View Source
var (
	// ErrInvalidEntityType is returned when functions like Get or Next are
	// passed a dst or src argument of invalid type.
	ErrInvalidEntityType = errors.New("datastore: invalid entity type")
	// ErrInvalidKey is returned when an invalid key is presented.
	ErrInvalidKey = errors.New("datastore: invalid key")
	// ErrNoSuchEntity is returned when no entity was found for a given key.
	ErrNoSuchEntity = errors.New("datastore: no such entity")
)
View Source
var Done = errors.New("datastore: query has no more results")

Done is returned when a query iteration has completed.

View Source
var ErrConcurrentTransaction = errors.New("datastore: concurrent transaction")

ErrConcurrentTransaction is returned when a transaction is rolled back due to a conflict with a concurrent transaction.

Functions

func LoadStruct

func LoadStruct(dst interface{}, p []Property) error

LoadStruct loads the properties from p to dst. dst must be a struct pointer.

func WithNamespace

func WithNamespace(parent context.Context, namespace string) context.Context

WithNamespace returns a new context that limits the scope its parent context with a Datastore namespace.

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is a client for reading and writing data in a datastore dataset.

func NewClient

func NewClient(ctx context.Context, projectID string, opts ...cloud.ClientOption) (*Client, error)

NewClient creates a new Client for a given dataset. If the project ID is empty, it is derived from the DATASTORE_DATASET environment variable.

func (*Client) AllocateIDs

func (c *Client) AllocateIDs(ctx context.Context, keys []*Key) ([]*Key, error)

AllocateIDs accepts a slice of incomplete keys and returns a slice of complete keys that are guaranteed to be valid in the datastore

func (*Client) Count

func (c *Client) Count(ctx context.Context, q *Query) (int, error)

Count returns the number of results for the given query.

func (*Client) Delete

func (c *Client) Delete(ctx context.Context, key *Key) error

Delete deletes the entity for the given key.

Example
package main

import (
	"github.com/tetrafolium/gcloud-golang/datastore"
	"golang.org/x/net/context"
)

func main() {
	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.
}
Output:

func (*Client) DeleteMulti

func (c *Client) DeleteMulti(ctx context.Context, keys []*Key) error

DeleteMulti is a batch version of Delete.

Example
package main

import (
	"github.com/tetrafolium/gcloud-golang/datastore"
	"golang.org/x/net/context"
)

func main() {
	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.
}
Output:

func (*Client) Get

func (c *Client) Get(ctx context.Context, key *Key, dst interface{}) error

Get loads the entity stored for key into dst, which must be a struct pointer or implement PropertyLoadSaver. If there is no such entity for the key, Get returns ErrNoSuchEntity.

The values of dst's unmatched struct fields are not modified, and matching slice-typed fields are not reset before appending to them. In particular, it is recommended to pass a pointer to a zero valued struct on each Get call.

ErrFieldMismatch is returned when a field is to be loaded into a different type than the one it was stored from, or when a field is missing or unexported in the destination struct. ErrFieldMismatch is only returned if dst is a struct pointer.

Example
package main

import (
	"time"

	"github.com/tetrafolium/gcloud-golang/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 main() {
	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.
}
Output:

func (*Client) GetAll

func (c *Client) GetAll(ctx context.Context, q *Query, dst interface{}) ([]*Key, error)

GetAll runs the provided query in the given context and returns all keys that match that query, as well as appending the values to dst.

dst must have type *[]S or *[]*S or *[]P, for some struct type S or some non- interface, non-pointer type P such that P or *P implements PropertyLoadSaver.

As a special case, *PropertyList is an invalid type for dst, even though a PropertyList is a slice of structs. It is treated as invalid to avoid being mistakenly passed when *[]PropertyList was intended.

The keys returned by GetAll will be in a 1-1 correspondence with the entities added to dst.

If q is a “keys-only” query, GetAll ignores dst and only returns the keys.

func (*Client) GetMulti

func (c *Client) GetMulti(ctx context.Context, keys []*Key, dst interface{}) error

GetMulti is a batch version of Get.

dst must be a []S, []*S, []I or []P, for some struct type S, some interface type I, or some non-interface non-pointer type P such that P or *P implements PropertyLoadSaver. If an []I, each element must be a valid dst for Get: it must be a struct pointer or implement PropertyLoadSaver.

As a special case, PropertyList is an invalid type for dst, even though a PropertyList is a slice of structs. It is treated as invalid to avoid being mistakenly passed when []PropertyList was intended.

Example
package main

import (
	"time"

	"github.com/tetrafolium/gcloud-golang/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 main() {
	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.
}
Output:

func (*Client) NewTransaction

func (c *Client) NewTransaction(ctx context.Context, opts ...TransactionOption) (*Transaction, error)

NewTransaction starts a new transaction.

func (*Client) Put

func (c *Client) Put(ctx context.Context, key *Key, src interface{}) (*Key, error)

Put saves the entity src into the datastore with key k. src must be a struct pointer or implement PropertyLoadSaver; if a struct pointer then any unexported fields of that struct will be skipped. If k is an incomplete key, the returned key will be a unique key generated by the datastore.

Example
package main

import (
	"time"

	"github.com/tetrafolium/gcloud-golang/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 main() {
	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.
}
Output:

Example (Upsert)
package main

import (
	"time"

	"github.com/tetrafolium/gcloud-golang/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 main() {
	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
}
Output:

func (*Client) PutMulti

func (c *Client) PutMulti(ctx context.Context, keys []*Key, src interface{}) ([]*Key, error)

PutMulti is a batch version of Put.

src must satisfy the same conditions as the dst argument to GetMulti.

Example
package main

import (
	"time"

	"github.com/tetrafolium/gcloud-golang/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 main() {
	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.
}
Output:

func (*Client) Run

func (c *Client) Run(ctx context.Context, q *Query) *Iterator

Run runs the given query in the given context.

func (*Client) RunInTransaction

func (c *Client) RunInTransaction(ctx context.Context, f func(tx *Transaction) error, opts ...TransactionOption) (*Commit, error)

RunInTransaction runs f in a transaction. f is invoked with a Transaction that f should use for all the transaction's datastore operations.

f must not call Commit or Rollback on the provided Transaction.

If f returns nil, RunInTransaction commits the transaction, returning the Commit and a nil error if it succeeds. If the commit fails due to a conflicting transaction, RunInTransaction retries f with a new Transaction. It gives up and returns ErrConcurrentTransaction after three failed attempts.

If f returns non-nil, then the transaction will be rolled back and RunInTransaction will return the same error. The function f is not retried.

Note that when f returns, the transaction is not committed. Calling code must not assume that any of f's changes have been committed until RunInTransaction returns nil.

Since f may be called multiple times, f should usually be idempotent. Note that Transaction.Get is not idempotent when unmarshaling slice fields.

type Commit

type Commit struct{}

Commit represents the result of a committed transaction.

func (*Commit) Key

func (c *Commit) Key(p *PendingKey) *Key

Key resolves a pending key handle into a final key.

type Cursor

type Cursor struct {
	// contains filtered or unexported fields
}

Cursor is an iterator's position. It can be converted to and from an opaque string. A cursor can be used from different HTTP requests, but only with a query with the same kind, ancestor, filter and order constraints.

func DecodeCursor

func DecodeCursor(s string) (Cursor, error)

Decode decodes a cursor from its base-64 string representation.

func (Cursor) String

func (c Cursor) String() string

String returns a base-64 string representation of a cursor.

type ErrFieldMismatch

type ErrFieldMismatch struct {
	StructType reflect.Type
	FieldName  string
	Reason     string
}

ErrFieldMismatch is returned when a field is to be loaded into a different type than the one it was stored from, or when a field is missing or unexported in the destination struct. StructType is the type of the struct pointed to by the destination argument passed to Get or to Iterator.Next.

func (*ErrFieldMismatch) Error

func (e *ErrFieldMismatch) Error() string

type Iterator

type Iterator struct {
	// contains filtered or unexported fields
}

Iterator is the result of running a query.

func (*Iterator) Cursor

func (t *Iterator) Cursor() (Cursor, error)

Cursor returns a cursor for the iterator's current location.

Example
package main

import (
	"log"
	"time"

	"github.com/tetrafolium/gcloud-golang/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 main() {
	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.
}
Output:

func (*Iterator) Next

func (t *Iterator) Next(dst interface{}) (*Key, error)

Next returns the key of the next result. When there are no more results, Done is returned as the error.

If the query is not keys only and dst is non-nil, it also loads the entity stored for that key into the struct pointer or PropertyLoadSaver dst, with the same semantics and possible errors as for the Get function.

type Key

type Key struct {
	// contains filtered or unexported fields
}

Key represents the datastore key for a stored entity, and is immutable.

func DecodeKey

func DecodeKey(encoded string) (*Key, error)

DecodeKey decodes a key from the opaque representation returned by Encode.

func NewIncompleteKey

func NewIncompleteKey(ctx context.Context, kind string, parent *Key) *Key

NewIncompleteKey creates a new incomplete key. kind cannot be empty.

Example
package main

import (
	"github.com/tetrafolium/gcloud-golang/datastore"
	"golang.org/x/net/context"
)

func main() {
	ctx := context.Background()
	// [START incomplete_key]
	taskKey := datastore.NewIncompleteKey(ctx, "Task", nil)
	// [END incomplete_key]
	_ = taskKey // Use the task key for datastore operations.
}
Output:

func NewKey

func NewKey(ctx context.Context, kind, name string, id int64, parent *Key) *Key

NewKey creates a new key. kind cannot be empty. Either one or both of name and id must be zero. If both are zero, the key returned is incomplete. parent must either be a complete key or nil.

Example
package main

import (
	"github.com/tetrafolium/gcloud-golang/datastore"
	"golang.org/x/net/context"
)

func main() {
	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.
}
Output:

Example (WithMultipleParents)
package main

import (
	"github.com/tetrafolium/gcloud-golang/datastore"
	"golang.org/x/net/context"
)

func main() {
	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.
}
Output:

Example (WithParent)
package main

import (
	"github.com/tetrafolium/gcloud-golang/datastore"
	"golang.org/x/net/context"
)

func main() {
	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.
}
Output:

func (*Key) Encode

func (k *Key) Encode() string

Encode returns an opaque representation of the key suitable for use in HTML and URLs. This is compatible with the Python and Java runtimes.

func (*Key) Equal

func (k *Key) Equal(o *Key) bool

func (*Key) GobDecode

func (k *Key) GobDecode(buf []byte) error

func (*Key) GobEncode

func (k *Key) GobEncode() ([]byte, error)

func (*Key) ID

func (k *Key) ID() int64

func (*Key) Incomplete

func (k *Key) Incomplete() bool

Complete returns whether the key does not refer to a stored entity.

func (*Key) Kind

func (k *Key) Kind() string

func (*Key) MarshalJSON

func (k *Key) MarshalJSON() ([]byte, error)

func (*Key) Name

func (k *Key) Name() string

func (*Key) Namespace

func (k *Key) Namespace() string

func (*Key) Parent

func (k *Key) Parent() *Key

func (*Key) SetParent

func (k *Key) SetParent(v *Key)

func (*Key) String

func (k *Key) String() string

String returns a string representation of the key.

func (*Key) UnmarshalJSON

func (k *Key) UnmarshalJSON(buf []byte) error

type MultiError

type MultiError []error

MultiError is returned by batch operations when there are errors with particular elements. Errors will be in a one-to-one correspondence with the input elements; successful elements will have a nil entry.

func (MultiError) Error

func (m MultiError) Error() string

type PendingKey

type PendingKey struct {
	// contains filtered or unexported fields
}

PendingKey represents the key for newly-inserted entity. It can be resolved into a Key by calling the Key method of Commit.

type Property

type Property struct {
	// Name is the property name.
	Name string
	// Value is the property value. The valid types are:
	//	- int64
	//	- bool
	//	- string
	//	- float64
	//	- *Key
	//	- time.Time
	//	- []byte (up to 1 megabyte in length)
	// This set is smaller than the set of valid struct field types that the
	// datastore can load and save. A Property Value cannot be a slice (apart
	// from []byte); use multiple Properties instead. Also, a Value's type
	// must be explicitly on the list above; it is not sufficient for the
	// underlying type to be on that list. For example, a Value of "type
	// myInt64 int64" is invalid. Smaller-width integers and floats are also
	// invalid. Again, this is more restrictive than the set of valid struct
	// field types.
	//
	// A Value will have an opaque type when loading entities from an index,
	// such as via a projection query. Load entities into a struct instead
	// of a PropertyLoadSaver when using a projection query.
	//
	// A Value may also be the nil interface value; this is equivalent to
	// Python's None but not directly representable by a Go struct. Loading
	// a nil-valued property into a struct will set that field to the zero
	// value.
	Value interface{}
	// NoIndex is whether the datastore cannot index this property.
	// If NoIndex is set to false, []byte values are limited to 1500 bytes and
	// string values are limited to 1500 bytes.
	NoIndex bool
	// Multiple is whether the entity can have multiple properties with
	// the same name. Even if a particular instance only has one property with
	// a certain name, Multiple should be true if a struct would best represent
	// it as a field of type []T instead of type T.
	Multiple bool
}

Property is a name/value pair plus some metadata. A datastore entity's contents are loaded and saved as a sequence of Properties. An entity can have multiple Properties with the same name, provided that p.Multiple is true on all of that entity's Properties with that name.

func SaveStruct

func SaveStruct(src interface{}) ([]Property, error)

SaveStruct returns the properties from src as a slice of Properties. src must be a struct pointer.

type PropertyList

type PropertyList []Property

PropertyList converts a []Property to implement PropertyLoadSaver.

func (*PropertyList) Load

func (l *PropertyList) Load(p []Property) error

Load loads all of the provided properties into l. It does not first reset *l to an empty slice.

func (*PropertyList) Save

func (l *PropertyList) Save() ([]Property, error)

Save saves all of l's properties as a slice of Properties.

type PropertyLoadSaver

type PropertyLoadSaver interface {
	Load([]Property) error
	Save() ([]Property, error)
}

PropertyLoadSaver can be converted from and to a slice of Properties.

type Query

type Query struct {
	// contains filtered or unexported fields
}

Query represents a datastore query.

Example
package main

import (
	"log"
	"time"

	"github.com/tetrafolium/gcloud-golang/datastore"
	"golang.org/x/net/context"
)

func main() {
	ctx := context.Background()
	client, err := datastore.NewClient(ctx, "project-id")
	if err != nil {
		log.Fatal(err)
	}

	// Count the number of the post entities.
	q := datastore.NewQuery("Post")
	n, err := client.Count(ctx, q)
	if err != nil {
		log.Fatal(err)
	}
	log.Println("There are %d posts.", n)

	// 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)
	// Use the iterator.
	_ = it

	// Order the posts by the number of comments they have recieved.
	datastore.NewQuery("Post").Order("-Comments")

	// Start listing from an offset and limit the results.
	datastore.NewQuery("Post").Offset(20).Limit(10)
}
Output:

Example (Basic)
package main

import (
	"fmt"
	"log"
	"time"

	"github.com/tetrafolium/gcloud-golang/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 main() {
	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]
}
Output:

Example (CompositeFilter)
package main

import (
	"github.com/tetrafolium/gcloud-golang/datastore"
)

func main() {
	// [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.
}
Output:

Example (InequalitySort)
package main

import (
	"github.com/tetrafolium/gcloud-golang/datastore"
)

func main() {
	// [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.
}
Output:

Example (InvalidInequalitySortA)
package main

import (
	"github.com/tetrafolium/gcloud-golang/datastore"
)

func main() {
	// [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.
}
Output:

Example (InvalidInequalitySortB)
package main

import (
	"github.com/tetrafolium/gcloud-golang/datastore"
)

func main() {
	// [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.
}
Output:

Example (KeyFilter)
package main

import (
	"github.com/tetrafolium/gcloud-golang/datastore"
	"golang.org/x/net/context"
)

func main() {
	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.
}
Output:

Example (Kindless)
package main

import (
	"github.com/tetrafolium/gcloud-golang/datastore"
)

func main() {
	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.
}
Output:

Example (PropertyFilter)
package main

import (
	"github.com/tetrafolium/gcloud-golang/datastore"
)

func main() {
	// [START property_filter]
	query := datastore.NewQuery("Task").Filter("Done =", false)
	// [END property_filter]
	_ = query // Use client.Run or client.GetAll to execute the query.
}
Output:

Example (SortAscending)
package main

import (
	"github.com/tetrafolium/gcloud-golang/datastore"
)

func main() {
	// [START ascending_sort]
	query := datastore.NewQuery("Task").Order("created")
	// [END ascending_sort]
	_ = query // Use client.Run or client.GetAll to execute the query.
}
Output:

Example (SortDescending)
package main

import (
	"github.com/tetrafolium/gcloud-golang/datastore"
)

func main() {
	// [START descending_sort]
	query := datastore.NewQuery("Task").Order("-created")
	// [END descending_sort]
	_ = query // Use client.Run or client.GetAll to execute the query.
}
Output:

Example (SortMulti)
package main

import (
	"github.com/tetrafolium/gcloud-golang/datastore"
)

func main() {
	// [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.
}
Output:

Example (Unindexed)
package main

import (
	"github.com/tetrafolium/gcloud-golang/datastore"
)

func main() {
	// [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.
}
Output:

func NewQuery

func NewQuery(kind string) *Query

NewQuery creates a new Query for a specific entity kind.

An empty kind means to return all entities, including entities created and managed by other App Engine features, and is called a kindless query. Kindless queries cannot include filters or sort orders on property values.

func (*Query) Ancestor

func (q *Query) Ancestor(ancestor *Key) *Query

Ancestor returns a derivative query with an ancestor filter. The ancestor should not be nil.

Example
package main

import (
	"github.com/tetrafolium/gcloud-golang/datastore"
	"golang.org/x/net/context"
)

func main() {
	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.
}
Output:

func (*Query) Distinct

func (q *Query) Distinct() *Query

Distinct returns a derivative query that yields de-duplicated entities with respect to the set of projected fields. It is only used for projection queries.

Example
package main

import (
	"github.com/tetrafolium/gcloud-golang/datastore"
)

func main() {
	// [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]
}
Output:

func (*Query) End

func (q *Query) End(c Cursor) *Query

End returns a derivative query with the given end point.

func (*Query) EventualConsistency

func (q *Query) EventualConsistency() *Query

EventualConsistency returns a derivative query that returns eventually consistent results. It only has an effect on ancestor queries.

Example
package main

import (
	"github.com/tetrafolium/gcloud-golang/datastore"
	"golang.org/x/net/context"
)

func main() {
	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.
}
Output:

func (*Query) Filter

func (q *Query) Filter(filterStr string, value interface{}) *Query

Filter returns a derivative query with a field-based filter. The filterStr argument must be a field name followed by optional space, followed by an operator, one of ">", "<", ">=", "<=", or "=". Fields are compared against the provided value using the operator. Multiple filters are AND'ed together. Field names which contain spaces, quote marks, or operator characters should be passed as quoted Go string literals as returned by strconv.Quote or the fmt package's %q verb.

Example (ArrayEquality)
package main

import (
	"github.com/tetrafolium/gcloud-golang/datastore"
)

func main() {
	// [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.
}
Output:

Example (ArrayInequality)
package main

import (
	"github.com/tetrafolium/gcloud-golang/datastore"
)

func main() {
	// [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.
}
Output:

Example (Inequality)
package main

import (
	"time"

	"github.com/tetrafolium/gcloud-golang/datastore"
)

func main() {
	// [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.
}
Output:

Example (InvalidInequality)
package main

import (
	"time"

	"github.com/tetrafolium/gcloud-golang/datastore"
)

func main() {
	// [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.
}
Output:

Example (Mixed)
package main

import (
	"time"

	"github.com/tetrafolium/gcloud-golang/datastore"
)

func main() {
	// [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.
}
Output:

func (*Query) KeysOnly

func (q *Query) KeysOnly() *Query

KeysOnly returns a derivative query that yields only keys, not keys and entities. It cannot be used with projection queries.

Example
package main

import (
	"github.com/tetrafolium/gcloud-golang/datastore"
	"golang.org/x/net/context"
)

func main() {
	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.
}
Output:

func (*Query) Limit

func (q *Query) Limit(limit int) *Query

Limit returns a derivative query that has a limit on the number of results returned. A negative value means unlimited.

Example
package main

import (
	"github.com/tetrafolium/gcloud-golang/datastore"
)

func main() {
	// [START limit]
	query := datastore.NewQuery("Task").Limit(5)
	// [END limit]
	_ = query // Use client.Run or client.GetAll to execute the query.
}
Output:

func (*Query) Offset

func (q *Query) Offset(offset int) *Query

Offset returns a derivative query that has an offset of how many keys to skip over before returning results. A negative value is invalid.

func (*Query) Order

func (q *Query) Order(fieldName string) *Query

Order returns a derivative query with a field-based sort order. Orders are applied in the order they are added. The default order is ascending; to sort in descending order prefix the fieldName with a minus sign (-). Field names which contain spaces, quote marks, or the minus sign should be passed as quoted Go string literals as returned by strconv.Quote or the fmt package's %q verb.

func (*Query) Project

func (q *Query) Project(fieldNames ...string) *Query

Project returns a derivative query that yields only the given fields. It cannot be used with KeysOnly.

Example
package main

import (
	"log"
	"time"

	"github.com/tetrafolium/gcloud-golang/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 main() {
	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]
}
Output:

func (*Query) Start

func (q *Query) Start(c Cursor) *Query

Start returns a derivative query with the given start point.

func (*Query) Transaction

func (q *Query) Transaction(t *Transaction) *Query

Transaction returns a derivative query that is associated with the given transaction.

All reads performed as part of the transaction will come from a single consistent snapshot. Furthermore, if the transaction is set to a serializable isolation level, another transaction cannot concurrently modify the data that is read or modified by this transaction.

type Transaction

type Transaction struct {
	// contains filtered or unexported fields
}

Transaction represents a set of datastore operations to be committed atomically.

Operations are enqueued by calling the Put and Delete methods on Transaction (or their Multi-equivalents). These operations are only committed when the Commit method is invoked. To ensure consistency, reads must be performed by using Transaction's Get method or by using the Transaction method when building a query.

A Transaction must be committed or rolled back exactly once.

Example
package main

import (
	"log"

	"github.com/tetrafolium/gcloud-golang/datastore"
	"golang.org/x/net/context"
)

func main() {
	ctx := context.Background()
	client, err := datastore.NewClient(ctx, "project-id")
	if err != nil {
		log.Fatal(err)
	}
	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.NewKey(ctx, "counter", "CounterA", 0, nil)

	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
		}
	}

}
Output:

Example (GetOrCreate)
package main

import (
	"time"

	"github.com/tetrafolium/gcloud-golang/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 main() {
	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.
}
Output:

Example (Insert)
package main

import (
	"log"
	"time"

	"github.com/tetrafolium/gcloud-golang/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 main() {
	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]
}
Output:

Example (RunQuery)
package main

import (
	"log"
	"time"

	"github.com/tetrafolium/gcloud-golang/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 main() {
	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.
}
Output:

Example (Update)
package main

import (
	"log"
	"time"

	"github.com/tetrafolium/gcloud-golang/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 main() {
	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]
}
Output:

func (*Transaction) Commit

func (t *Transaction) Commit() (*Commit, error)

Commit applies the enqueued operations atomically.

func (*Transaction) Delete

func (t *Transaction) Delete(key *Key) error

Delete is the transaction-specific version of the package function Delete. Delete enqueues the deletion of the entity for the given key, to be committed atomically upon calling Commit.

func (*Transaction) DeleteMulti

func (t *Transaction) DeleteMulti(keys []*Key) error

DeleteMulti is a batch version of Delete.

func (*Transaction) Get

func (t *Transaction) Get(key *Key, dst interface{}) error

Get is the transaction-specific version of the package function Get. All reads performed during the transaction will come from a single consistent snapshot. Furthermore, if the transaction is set to a serializable isolation level, another transaction cannot concurrently modify the data that is read or modified by this transaction.

func (*Transaction) GetMulti

func (t *Transaction) GetMulti(keys []*Key, dst interface{}) error

GetMulti is a batch version of Get.

func (*Transaction) Put

func (t *Transaction) Put(key *Key, src interface{}) (*PendingKey, error)

Put is the transaction-specific version of the package function Put.

Put returns a PendingKey which can be resolved into a Key using the return value from a successful Commit. If key is an incomplete key, the returned pending key will resolve to a unique key generated by the datastore.

func (*Transaction) PutMulti

func (t *Transaction) PutMulti(keys []*Key, src interface{}) ([]*PendingKey, error)

PutMulti is a batch version of Put. One PendingKey is returned for each element of src in the same order.

func (*Transaction) Rollback

func (t *Transaction) Rollback() error

Rollback abandons a pending transaction.

type TransactionOption

type TransactionOption interface {
	// contains filtered or unexported methods
}

A TransactionOption configures the Transaction returned by NewTransaction.

var (
	// Snapshot causes the transaction to enforce a snapshot isolation level.
	Snapshot TransactionOption = isolation{pb.BeginTransactionRequest_SNAPSHOT}
	// Serializable causes the transaction to enforce a serializable isolation level.
	Serializable TransactionOption = isolation{pb.BeginTransactionRequest_SERIALIZABLE}
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL