github.com/timstclair/heapster@v0.20.0-alpha1/Godeps/_workspace/src/google.golang.org/appengine/datastore/doc.go (about)

     1  // Copyright 2011 Google Inc. All rights reserved.
     2  // Use of this source code is governed by the Apache 2.0
     3  // license that can be found in the LICENSE file.
     4  
     5  /*
     6  Package datastore provides a client for App Engine's datastore service.
     7  
     8  
     9  Basic Operations
    10  
    11  Entities are the unit of storage and are associated with a key. A key
    12  consists of an optional parent key, a string application ID, a string kind
    13  (also known as an entity type), and either a StringID or an IntID. A
    14  StringID is also known as an entity name or key name.
    15  
    16  It is valid to create a key with a zero StringID and a zero IntID; this is
    17  called an incomplete key, and does not refer to any saved entity. Putting an
    18  entity into the datastore under an incomplete key will cause a unique key
    19  to be generated for that entity, with a non-zero IntID.
    20  
    21  An entity's contents are a mapping from case-sensitive field names to values.
    22  Valid value types are:
    23    - signed integers (int, int8, int16, int32 and int64),
    24    - bool,
    25    - string,
    26    - float32 and float64,
    27    - []byte (up to 1 megabyte in length),
    28    - any type whose underlying type is one of the above predeclared types,
    29    - ByteString,
    30    - *Key,
    31    - time.Time (stored with microsecond precision),
    32    - appengine.BlobKey,
    33    - appengine.GeoPoint,
    34    - structs whose fields are all valid value types,
    35    - slices of any of the above.
    36  
    37  Slices of structs are valid, as are structs that contain slices. However, if
    38  one struct contains another, then at most one of those can be repeated. This
    39  disqualifies recursively defined struct types: any struct T that (directly or
    40  indirectly) contains a []T.
    41  
    42  The Get and Put functions load and save an entity's contents. An entity's
    43  contents are typically represented by a struct pointer.
    44  
    45  Example code:
    46  
    47  	type Entity struct {
    48  		Value string
    49  	}
    50  
    51  	func handle(w http.ResponseWriter, r *http.Request) {
    52  		ctx := appengine.NewContext(r)
    53  
    54  		k := datastore.NewKey(ctx, "Entity", "stringID", 0, nil)
    55  		e := new(Entity)
    56  		if err := datastore.Get(ctx, k, e); err != nil {
    57  			http.Error(w, err.Error(), 500)
    58  			return
    59  		}
    60  
    61  		old := e.Value
    62  		e.Value = r.URL.Path
    63  
    64  		if _, err := datastore.Put(ctx, k, e); err != nil {
    65  			http.Error(w, err.Error(), 500)
    66  			return
    67  		}
    68  
    69  		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
    70  		fmt.Fprintf(w, "old=%q\nnew=%q\n", old, e.Value)
    71  	}
    72  
    73  GetMulti, PutMulti and DeleteMulti are batch versions of the Get, Put and
    74  Delete functions. They take a []*Key instead of a *Key, and may return an
    75  appengine.MultiError when encountering partial failure.
    76  
    77  
    78  Properties
    79  
    80  An entity's contents can be represented by a variety of types. These are
    81  typically struct pointers, but can also be any type that implements the
    82  PropertyLoadSaver interface. If using a struct pointer, you do not have to
    83  explicitly implement the PropertyLoadSaver interface; the datastore will
    84  automatically convert via reflection. If a struct pointer does implement that
    85  interface then those methods will be used in preference to the default
    86  behavior for struct pointers. Struct pointers are more strongly typed and are
    87  easier to use; PropertyLoadSavers are more flexible.
    88  
    89  The actual types passed do not have to match between Get and Put calls or even
    90  across different App Engine requests. It is valid to put a *PropertyList and
    91  get that same entity as a *myStruct, or put a *myStruct0 and get a *myStruct1.
    92  Conceptually, any entity is saved as a sequence of properties, and is loaded
    93  into the destination value on a property-by-property basis. When loading into
    94  a struct pointer, an entity that cannot be completely represented (such as a
    95  missing field) will result in an ErrFieldMismatch error but it is up to the
    96  caller whether this error is fatal, recoverable or ignorable.
    97  
    98  By default, for struct pointers, all properties are potentially indexed, and
    99  the property name is the same as the field name (and hence must start with an
   100  upper case letter). Fields may have a `datastore:"name,options"` tag. The tag
   101  name is the property name, which must be one or more valid Go identifiers
   102  joined by ".", but may start with a lower case letter. An empty tag name means
   103  to just use the field name. A "-" tag name means that the datastore will
   104  ignore that field. If options is "noindex" then the field will not be indexed.
   105  If the options is "" then the comma may be omitted. There are no other
   106  recognized options.
   107  
   108  Fields (except for []byte) are indexed by default. Strings longer than 1500
   109  bytes cannot be indexed; fields used to store long strings should be
   110  tagged with "noindex". Similarly, ByteStrings longer than 1500 bytes cannot be
   111  indexed.
   112  
   113  Example code:
   114  
   115  	// A and B are renamed to a and b.
   116  	// A, C and J are not indexed.
   117  	// D's tag is equivalent to having no tag at all (E).
   118  	// I is ignored entirely by the datastore.
   119  	// J has tag information for both the datastore and json packages.
   120  	type TaggedStruct struct {
   121  		A int `datastore:"a,noindex"`
   122  		B int `datastore:"b"`
   123  		C int `datastore:",noindex"`
   124  		D int `datastore:""`
   125  		E int
   126  		I int `datastore:"-"`
   127  		J int `datastore:",noindex" json:"j"`
   128  	}
   129  
   130  
   131  Structured Properties
   132  
   133  If the struct pointed to contains other structs, then the nested or embedded
   134  structs are flattened. For example, given these definitions:
   135  
   136  	type Inner1 struct {
   137  		W int32
   138  		X string
   139  	}
   140  
   141  	type Inner2 struct {
   142  		Y float64
   143  	}
   144  
   145  	type Inner3 struct {
   146  		Z bool
   147  	}
   148  
   149  	type Outer struct {
   150  		A int16
   151  		I []Inner1
   152  		J Inner2
   153  		Inner3
   154  	}
   155  
   156  then an Outer's properties would be equivalent to those of:
   157  
   158  	type OuterEquivalent struct {
   159  		A     int16
   160  		IDotW []int32  `datastore:"I.W"`
   161  		IDotX []string `datastore:"I.X"`
   162  		JDotY float64  `datastore:"J.Y"`
   163  		Z     bool
   164  	}
   165  
   166  If Outer's embedded Inner3 field was tagged as `datastore:"Foo"` then the
   167  equivalent field would instead be: FooDotZ bool `datastore:"Foo.Z"`.
   168  
   169  If an outer struct is tagged "noindex" then all of its implicit flattened
   170  fields are effectively "noindex".
   171  
   172  
   173  The PropertyLoadSaver Interface
   174  
   175  An entity's contents can also be represented by any type that implements the
   176  PropertyLoadSaver interface. This type may be a struct pointer, but it does
   177  not have to be. The datastore package will call Load when getting the entity's
   178  contents, and Save when putting the entity's contents.
   179  Possible uses include deriving non-stored fields, verifying fields, or indexing
   180  a field only if its value is positive.
   181  
   182  Example code:
   183  
   184  	type CustomPropsExample struct {
   185  		I, J int
   186  		// Sum is not stored, but should always be equal to I + J.
   187  		Sum int `datastore:"-"`
   188  	}
   189  
   190  	func (x *CustomPropsExample) Load(ps []datastore.Property) error {
   191  		// Load I and J as usual.
   192  		if err := datastore.LoadStruct(x, ps); err != nil {
   193  			return err
   194  		}
   195  		// Derive the Sum field.
   196  		x.Sum = x.I + x.J
   197  		return nil
   198  	}
   199  
   200  	func (x *CustomPropsExample) Save() ([]datastore.Property, error) {
   201  		// Validate the Sum field.
   202  		if x.Sum != x.I + x.J {
   203  			return errors.New("CustomPropsExample has inconsistent sum")
   204  		}
   205  		// Save I and J as usual. The code below is equivalent to calling
   206  		// "return datastore.SaveStruct(x)", but is done manually for
   207  		// demonstration purposes.
   208  		return []datastore.Property{
   209  			{
   210  				Name:  "I",
   211  				Value: int64(x.I),
   212  			},
   213  			{
   214  				Name:  "J",
   215  				Value: int64(x.J),
   216  			},
   217  		}
   218  	}
   219  
   220  The *PropertyList type implements PropertyLoadSaver, and can therefore hold an
   221  arbitrary entity's contents.
   222  
   223  
   224  Queries
   225  
   226  Queries retrieve entities based on their properties or key's ancestry. Running
   227  a query yields an iterator of results: either keys or (key, entity) pairs.
   228  Queries are re-usable and it is safe to call Query.Run from concurrent
   229  goroutines. Iterators are not safe for concurrent use.
   230  
   231  Queries are immutable, and are either created by calling NewQuery, or derived
   232  from an existing query by calling a method like Filter or Order that returns a
   233  new query value. A query is typically constructed by calling NewQuery followed
   234  by a chain of zero or more such methods. These methods are:
   235    - Ancestor and Filter constrain the entities returned by running a query.
   236    - Order affects the order in which they are returned.
   237    - Project constrains the fields returned.
   238    - Distinct de-duplicates projected entities.
   239    - KeysOnly makes the iterator return only keys, not (key, entity) pairs.
   240    - Start, End, Offset and Limit define which sub-sequence of matching entities
   241      to return. Start and End take cursors, Offset and Limit take integers. Start
   242      and Offset affect the first result, End and Limit affect the last result.
   243      If both Start and Offset are set, then the offset is relative to Start.
   244      If both End and Limit are set, then the earliest constraint wins. Limit is
   245      relative to Start+Offset, not relative to End. As a special case, a
   246      negative limit means unlimited.
   247  
   248  Example code:
   249  
   250  	type Widget struct {
   251  		Description string
   252  		Price       int
   253  	}
   254  
   255  	func handle(w http.ResponseWriter, r *http.Request) {
   256  		ctx := appengine.NewContext(r)
   257  		q := datastore.NewQuery("Widget").
   258  			Filter("Price <", 1000).
   259  			Order("-Price")
   260  		b := new(bytes.Buffer)
   261  		for t := q.Run(ctx); ; {
   262  			var x Widget
   263  			key, err := t.Next(&x)
   264  			if err == datastore.Done {
   265  				break
   266  			}
   267  			if err != nil {
   268  				serveError(ctx, w, err)
   269  				return
   270  			}
   271  			fmt.Fprintf(b, "Key=%v\nWidget=%#v\n\n", key, x)
   272  		}
   273  		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
   274  		io.Copy(w, b)
   275  	}
   276  
   277  
   278  Transactions
   279  
   280  RunInTransaction runs a function in a transaction.
   281  
   282  Example code:
   283  
   284  	type Counter struct {
   285  		Count int
   286  	}
   287  
   288  	func inc(ctx context.Context, key *datastore.Key) (int, error) {
   289  		var x Counter
   290  		if err := datastore.Get(ctx, key, &x); err != nil && err != datastore.ErrNoSuchEntity {
   291  			return 0, err
   292  		}
   293  		x.Count++
   294  		if _, err := datastore.Put(ctx, key, &x); err != nil {
   295  			return 0, err
   296  		}
   297  		return x.Count, nil
   298  	}
   299  
   300  	func handle(w http.ResponseWriter, r *http.Request) {
   301  		ctx := appengine.NewContext(r)
   302  		var count int
   303  		err := datastore.RunInTransaction(ctx, func(ctx context.Context) error {
   304  			var err1 error
   305  			count, err1 = inc(ctx, datastore.NewKey(ctx, "Counter", "singleton", 0, nil))
   306  			return err1
   307  		}, nil)
   308  		if err != nil {
   309  			serveError(ctx, w, err)
   310  			return
   311  		}
   312  		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
   313  		fmt.Fprintf(w, "Count=%d", count)
   314  	}
   315  */
   316  package datastore