doc.go 11 KB

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