google.golang.org/appengine/datastore 包 (v1.6.8)

数据存储区包为 App Engine 的数据存储区服务提供了一个客户端。

基本运算

实体是存储单元,与键相关联。 键由一个可选的父键、一个字符串应用 ID、一个键类型(也称为实体类型)以及一个 StringID 或 IntID 组成。StringID 也称为实体名称或键名称。

可以创建一个 StringID 为零、IntID 为零的键;该键称为不完整键,而且不引用任何已保存的实体。 将一个实体放入数据存储区的不完整键下将导致系统为该实体生成具有非零 IntID 的唯一键。

一个实体的内容是从区分大小写的字段名称到值的映射。 有效的值类型包括:

  • 有符号整数(int、int8、int16、int32 和 int64),
  • bool,
  • string,
  • float32 和 float64,
  • []byte(最长 1 兆字节),
  • 底层类型是上述预声明类型之一的任何类型,
  • ByteString,
  • *Key,
  • time.Time(精度为微秒),
  • appengine.BlobKey,
  • appengine.GeoPoint,
  • 字段均为有效值类型的结构体;
  • 上述任何切片。

结构体切片是有效的,包含切片的结构体也是如此。 但是,如果一个结构体包含另一个结构体,则最多只能重复其中一个结构体。这样就不会产生以递归方式定义的结构体类型:任何(直接或间接)包含 []T 的结构体 T。

Get 和 Put 函数会加载并保存实体的内容。 实体的内容通常由结构体指针表示。

示例代码:

type Entity struct {
    Value string
}

func handle(w http.ResponseWriter, r *http.Request) {
    ctx := appengine.NewContext(r)

    k := datastore.NewKey(ctx, "Entity", "stringID", 0, nil)
    e := new(Entity)
    if err := datastore.Get(ctx, k, e); err != nil {
        http.Error(w, err.Error(), 500)
        return
    }

    old := e.Value
    e.Value = r.URL.Path

    if _, err := datastore.Put(ctx, k, e); err != nil {
        http.Error(w, err.Error(), 500)
        return
    }

    w.Header().Set("Content-Type", "text/plain; charset=utf-8")
    fmt.Fprintf(w, "old=%q\nnew=%q\n", old, e.Value)
}

GetMulti、PutMulti 和 DeleteMulti 分别是 Get、Put 和 Delete 函数的批处理版本。 其采用的是 []*Key 而不是 *Key,而且在遇到部分失败时可能会返回 appengine.MultiError。

属性

实体的内容可以用各种类型表示。 这些类型通常是结构体指针,但也可以是实现 PropertyLoadSaver 接口的任何类型。如果您使用结构体指针,则不必显式实现 PropertyLoadSaver 接口;数据存储区将通过反射自动转换。如果结构体指针确实实现了该接口,则系统将优先使用这些方法,而不是结构体指针的默认行为。结构体指针的类型更强,更易于使用;PropertyLoadSavers 更灵活。

传递的实际类型不必在 Get 和 Put 调用之间匹配,甚至不必在不同的数据存储区调用之间匹配。可以放置 *PropertyList 并获取与 *myStruct 相同的实体,也可以放置 *myStruct0 并获取 *myStruct1。 从概念上讲,任何实体都保存为一系列属性,并且会按属性逐个地加载到目标值中。 加载到结构体指针时,无法完全表示的实体(例如缺少的字段)将导致 ErrFieldMismatch 错误,但由调用者决定此错误是严重错误、可恢复错误还是可忽略错误。

默认情况下,对于结构体指针,所有属性都可能被编入索引,并且属性名称与字段名称相同(因此字段名称必须以大写字母开头)。

字段可能具有 datastore:"name,options" 标记。标记名称是属性名称,必须是由“.”连接的一个或多个有效 Go 标识符,但可以在开头使用小写字母。如果标记名称为空,则表示只使用字段名称。如果标记名称为“-”,则表示数据存储区将忽略该字段。

唯一的有效选项是“omitempty”和“noindex”。

如果选项包括“omtempty”且字段的值为空,则保存时将忽略该字段。空值为 false、0、任何 nil 接口值以及任何长度为 0 的数组、切片、映射或字符串。结构体字段值不能为空。

如果选项包括“noindex”,则表示字段将不会被编入索引。默认情况下,所有字段都会编入索引。长度超过 1500 字节的字符串或字节切片无法编入索引;用于存储长字符串和字节切片的字段必须带有“noindex”标记,否则将导致 Put 操作失败。

要同时使用多个选项,请用英文逗号分隔。顺序无关紧要。

如果选项为“”,则表示逗号可能会被省略。

示例代码:

// A and B are renamed to a and b.
// A, C and J are not indexed.
// D's tag is equivalent to having no tag at all (E).
// I is ignored entirely by the datastore.
// J has tag information for both the datastore and json packages.
type TaggedStruct struct {
    A int `datastore:"a,noindex"`
    B int `datastore:"b"`
    C int `datastore:",noindex"`
    D int `datastore:""`
    E int
    I int `datastore:"-"`
    J int `datastore:",noindex" json:"j"`
}

结构化属性

如果指向的结构体包含其他结构体,则嵌套或嵌入的结构体会被展平。 例如,给定下列定义:

type Inner1 struct {
    W int32
    X string
}

type Inner2 struct {
    Y float64
}

type Inner3 struct {
    Z bool
}

type Outer struct {
    A int16
    I []Inner1
    J Inner2
    Inner3
}

然后,Outer 的属性将等同于以下结构体的属性:

type OuterEquivalent struct {
    A     int16
    IDotW []int32  `datastore:"I.W"`
    IDotX []string `datastore:"I.X"`
    JDotY float64  `datastore:"J.Y"`
    Z     bool
}

如果 Outer 的嵌入 Inner3 字段标记为 datastore:"Foo",则等效字段将为:FooDotZ bool datastore:"Foo.Z"

如果外部结构体标记为“noindex”,则其所有隐式展平字段实际上是“noindex”。

PropertyLoadSaver 接口

实体的内容也可以由实现 PropertyLoadSaver 接口的任何类型表示。 此类型可能是结构体指针,但并非必须是结构体指针。获取实体的内容时,数据存储区包将调用 Load;而在放置实体内容时,数据存储区包会调用 Save。 可能的用途包括提取非存储字段、验证字段或者只有在字段值为正数时才将字段编入索引。

示例代码:

type CustomPropsExample struct {
    I, J int
    // Sum is not stored, but should always be equal to I + J.
    Sum int `datastore:"-"`
}

func (x *CustomPropsExample) Load(ps []datastore.Property) error {
    // Load I and J as usual.
    if err := datastore.LoadStruct(x, ps); err != nil {
        return err
    }
    // Derive the Sum field.
    x.Sum = x.I + x.J
    return nil
}

func (x *CustomPropsExample) Save() ([]datastore.Property, error) {
    // Validate the Sum field.
    if x.Sum != x.I + x.J {
        return nil, errors.New("CustomPropsExample has inconsistent sum")
    }
    // Save I and J as usual. The code below is equivalent to calling
    // "return datastore.SaveStruct(x)", but is done manually for
    // demonstration purposes.
    return []datastore.Property{
        {
            Name:  "I",
            Value: int64(x.I),
        },
        {
            Name:  "J",
            Value: int64(x.J),
        },
    }, nil
}

*PropertyList 类型可以实现 PropertyLoadSaver,因此可以保存任意实体的内容。

查询

查询会根据其属性或键的祖先检索实体。 运行查询会生成结果迭代器:键或(键,实体)对。 查询可重复使用,您可以安全地调用 Query。此外,可从并发 Goroutine 运行查询。迭代器对于并发使用不安全。

查询是不可变的,可以通过调用 NewQuery 来创建,也可以通过调用返回新查询值的 Filter 或 Order 等方法从现有查询派生。 通常,可通过依次调用 NewQuery 以及零个或多个此类方法的链来构造查询。这些方法包括:

  • Ancestor 和 Filter 会限制通过运行查询返回的实体。
  • Order 会影响其返回顺序。
  • Project 限制返回的字段。
  • Distinct 会删除重复的投影实体。
  • KeysOnly 使迭代器只返回键,而不是返回(键, 实体)对。
  • Start、End、Offset 和 Limit 定义要返回的匹配实体的子序列。Start 和 End 采用游标,Offset 和 Limit 采用整数。Start 和 Offset 会影响第一个结果,End 和 Limit 会影响最后一个结果。如果同时设置了 Start 和 offset,则偏移量相对于 Start。如果同时设置了 End 和 Limit,则以最早的限制条件为准。Limit 相对于 Start+Offset,而不是相对于 End。特殊情况下,负值限制意味着无限制。

示例代码:

type Widget struct {
    Description string
    Price       int
}

func handle(w http.ResponseWriter, r *http.Request) {
    ctx := appengine.NewContext(r)
    q := datastore.NewQuery("Widget").
        Filter("Price <", 1000).
        Order("-Price")
    b := new(bytes.Buffer)
    for t := q.Run(ctx); ; {
        var x Widget
        key, err := t.Next(&x)
        if err == datastore.Done {
            break
        }
        if err != nil {
            serveError(ctx, w, err)
            return
        }
        fmt.Fprintf(b, "Key=%v\nWidget=%#v\n\n", key, x)
    }
    w.Header().Set("Content-Type", "text/plain; charset=utf-8")
    io.Copy(w, b)
}

事务

RunInTransaction 在事务中运行一个函数。

示例代码:

type Counter struct {
    Count int
}

func inc(ctx context.Context, key *datastore.Key) (int, error) {
    var x Counter
    if err := datastore.Get(ctx, key, &x); err != nil && err != datastore.ErrNoSuchEntity {
        return 0, err
    }
    x.Count++
    if _, err := datastore.Put(ctx, key, &x); err != nil {
        return 0, err
    }
    return x.Count, nil
}

func handle(w http.ResponseWriter, r *http.Request) {
    ctx := appengine.NewContext(r)
    var count int
    err := datastore.RunInTransaction(ctx, func(ctx context.Context) error {
        var err1 error
        count, err1 = inc(ctx, datastore.NewKey(ctx, "Counter", "singleton", 0, nil))
        return err1
    }, nil)
    if err != nil {
        serveError(ctx, w, err)
        return
    }
    w.Header().Set("Content-Type", "text/plain; charset=utf-8")
    fmt.Fprintf(w, "Count=%d", count)
}

元数据

数据存储区包提供 App Engine 的某些数据存储区元数据的访问权限。 此元数据包含有关数据存储区中的实体组、命名空间、实体种类和属性的信息,以及每个属性的属性表示形式。

示例代码:

func handle(w http.ResponseWriter, r *http.Request) {
    // Print all the kinds in the datastore, with all the indexed
    // properties (and their representations) for each.
    ctx := appengine.NewContext(r)

    kinds, err := datastore.Kinds(ctx)
    if err != nil {
        serveError(ctx, w, err)
        return
    }

    w.Header().Set("Content-Type", "text/plain; charset=utf-8")
    for _, kind := range kinds {
        fmt.Fprintf(w, "%s:\n", kind)
        props, err := datastore.KindProperties(ctx, kind)
        if err != nil {
            fmt.Fprintln(w, "\t(unable to retrieve properties)")
            continue
        }
        for p, rep := range props {
            fmt.Fprintf(w, "\t-%s (%s)\n", p, strings.Join(rep, ", "))
        }
    }
}

变量

ErrInvalidEntityType、ErrInvalidKey、ErrNoSuchEntity

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")
)

完成

var Done = errors.New("datastore: query has no more results")

查询迭代完成时将返回 Done。

ErrConcurrentTransaction

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

如果事务因与并发事务冲突而回滚,则系统将返回 ErrConcurrentTransaction。

函数

func AllocateIDRange

func AllocateIDRange(c context.Context, kind string, parent *Key, start, end int64) (err error)

AllocateIDRange 会为特定端点分配一组 ID。范围含下限和上限边界值。一旦分配了这些 ID,您可以手动将其指定给新建的实体。

数据存储区的自动 ID 分配器从不分配已经(通过自动 ID 分配或通过显式 AllocateIDs 调用)分配的键。因此,写入到给定键范围的实体永远也不会被覆盖。但是,在此范围中写入的实体如果具有手动指定的键,此实体可能会覆盖现有实体(或由不同请求写入的新实体),具体取决于返回的错误。

仅当您具有要保留的现有数字 ID 范围时才使用此项(例如,批量加载已具有 ID 的实体)。如果您对接收的 ID 并不在意,请改用 AllocateIDs。

如果范围分配成功,AllocateIDRange 会返回 nil。如果一个或多个实体 ID 在指定范围内已存在,则会返回 KeyRangeCollisionError。如果 Datastore 已缓存此范围内的 ID(例如,来自先前调用 AllocateIDRange),则它会返回 KeyRangeContentionError。其他类型的错误表示参数有问题或直接从 Datastore 返回的错误。

func AllocateIDs

func AllocateIDs(c context.Context, kind string, parent *Key, n int) (low, high int64, err error)

AllocateIDs 会返回整数 ID 的范围,其中包含 n 个由指定 kind 和 parent 组合而成的 ID。kind 不能为空;parent 可能为 nil。 数据存储区的自动 ID 序列生成器将不会使用所返回范围中的 ID,但这些 ID 可以与 NewKey 一起使用而不会产生冲突。

范围含下限值,但不含上限值。 换句话说,有效的 intIDs x 满足以下条件:“下限值 <= x && x < 上限值”。

如果没有返回错误,则“下限值 + n == 上限值”。

func Delete

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

Delete 删除给定键的实体。

func DeleteMulti

func DeleteMulti(c context.Context, key []*Key) error

DeleteMulti 是 Delete 的批处理版本。

func EnableKeyConversion

func EnableKeyConversion(ctx context.Context)

EnableKeyConversion 支持与 Cloud Datastore 客户端库 (cloud.google.com/go/datastore) 编码的密钥兼容性。Cloud Datastore 客户端库生成的编码密钥将解码为 App Engine Datastore 密钥。

如果在 App Engine 第一代运行时中运行,则提供的上下文必须是 App Engine 上下文。这可以在 /_ah/start 处理程序中调用。可以进行多次调用,并且调用费用低,因此还可以作为中间件插入。

启用密钥兼容性不会影响 Key.Encode 使用的编码格式,它只会扩展可以使用 DecodeKey 解码的密钥类型。

func Get

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

Get 会将为 k 存储的实体加载到 dst 中,而 dst 必须是结构体指针,或者必须实现 PropertyLoadSaver。 如果该键没有此类实体,则 Get 会返回 ErrNoSuchEntity。

dst 的不匹配结构体字段的值不会被修改,而且匹配的切片类型字段在附加到这些字段之前不会被重置。 具体来说,建议在每次进行 Get 调用时将指针传递给零值结构体。

将字段加载到与其先前存储类型不同的类型时,或者在目标结构体中缺少或未导出字段时,系统将返回 ErrFieldMismatch。只有在 dst 是结构体指针时,Get 才会返回 ErrFieldMismatch。

func GetMulti

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

GetMulti 是 Get 的批处理版本。

对于以下类型,dst 必须是 []S、[]*S、[]I 或 []P:某些结构体类型 S、某些接口类型 I 或某些非接口非指针类型 P(使得 P 或 *P 可以实现 PropertyLoadSaver)。 如果 dst 为 []I,则对于 Get,每个元素必须是有效的 dst:dst 必须是必须是结构体指针,或者必须实现 PropertyLoadSaver。

特殊情况下,PropertyList 是 dst 的无效类型,即使 PropertyList 是结构体的切片。 PropertyList 会被视为无效,以免在本应传递 []PropertyList 时被错误传递。

func KindProperties

func KindProperties(ctx context.Context, kind string) (map[string][]string, error)

KindProperties 会返回所有已编入索引的给定种类的属性。 属性以属性名称到表示形式类型切片的映射形式返回。 受支持的 Go 属性类型的表示形式类型如下:

"INT64":     signed integers and time.Time
"DOUBLE":    float32 and float64
"BOOLEAN":   bool
"STRING":    string, []byte and ByteString
"POINT":     appengine.GeoPoint
"REFERENCE": *Key
"USER":      (not used in the Go runtime)

func Kinds

func Kinds(ctx context.Context) ([]string, error)

Kinds 会返回当前命名空间中所有种类的名称。

func LoadStruct

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

LoadStruct 会将属性从 p 加载到 dst。dst 必须是结构体指针。

func Namespaces

func Namespaces(ctx context.Context) ([]string, error)

Namespaces 会返回所有数据存储区命名空间。

func RunInTransaction

func RunInTransaction(c context.Context, f func(tc context.Context) error, opts *TransactionOptions) error

RunInTransaction 在事务中运行 f。 它在 f 应该用于所有 App Engine 操作的事务上下文 tc 中调用 f。

如果 f 返回 nil,则 RunInTransaction 会尝试提交事务,如果成功,则返回 nil。 如果因事务冲突而导致提交失败,则 RunInTransaction 会重新尝试运行 f,并且每次都使用新的事务上下文。如果三次尝试均失败,RunInTransaction 将放弃尝试,并返回 ErrConcurrentTransaction。可以通过指定 TransactionOptions.Attempts 来配置尝试次数。

如果 f 返回非 nil,则所有数据存储区更改都将不会应用,而 RunInTransaction 会返回相同的错误。 函数 f 不会重试。

请注意,在 f 返回时,事务尚未提交。 调用代码时必须谨慎,直到 RunInTransaction 返回 nil 后,才能假设 f 的所有更改都已经提交。

由于 f 可能被调用多次,因此 f 通常应该具有幂等性。 datastore.Get 在分解切片字段时不是幂等的。

不支持使用嵌套的事务;c 不能用作事务上下文。

ByteString

type ByteString []byte

ByteString 是可以编入索引的短字节切片(最多 1500 字节)。

Cursor

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

Cursor 是迭代器的位置, 可以与不透明字符串进行相互转换。您可以通过不同的 HTTP 请求使用游标,但游标只能用于具有相同种类、祖先、过滤条件和顺序限制条件的查询。

func DecodeCursor

func DecodeCursor(s string) (Cursor, error)

DecodeCursor 通过游标的 base-64 字符串表示形式对游标进行解码。

func (Cursor) String

func (c Cursor) String() string

String 会返回游标的 Base-64 字符串表示形式。

Entity

type Entity struct {
	Key        *Key
	Properties []Property
}

Entity 是嵌套结构体的值类型。 此类型仅用于 Property 的值。

ErrFieldMismatch

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

将字段加载到与其先前存储类型不同的类型时,或者在目标结构体中缺少或未导出字段时,系统将返回 ErrFieldMismatch。StructType 是传递给 Get 或 Iterator.Next 的目标参数所指向的结构体的类型。

func (*ErrFieldMismatch) Error

func (e *ErrFieldMismatch) Error() string

Iterator

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

Iterator 是运行查询的结果。

func (*Iterator) Cursor

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

Cursor 会返回迭代器当前位置的游标。

func (*Iterator) Next

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

Next 会返回下一个结果的键。 如果没有更多结果,Next 会将 Done 作为错误返回。

如果查询不只是键,而且 dst 是非 nil,则 Next 还会将为该键存储的实体加载到结构体指针或 PropertyLoadSaver dst 中,该函数的语义与 Get 函数相同,也可能会发生与 Get 函数相同的错误。

Key

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

Key 表示存储实体的数据存储区键,它是不可变的。

func DecodeKey

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

DecodeKey 会通过 Encode 所返回的不透明表示法对键进行解码。

func NewIncompleteKey

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

NewIncompleteKey 会创建一个新的不完整键。 kind 不能为空。

func NewKey

func NewKey(c context.Context, kind, stringID string, intID int64, parent *Key) *Key

NewKey 会创建一个新键。 kind 不能为空。 stringID 和/或 intID 必须为零。 如果两者都为零,则表示所返回的键是不完整的。 parent 必须是完整的键或者 nil。

func Put

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

Put 会将实体 src 保存到键为 k 的数据存储区。src 必须是结构体指针,或者必须实现 PropertyLoadSaver;如果 src 是结构体指针,则系统将跳过该结构体的任何未导出字段。 如果 k 是不完整的键,则所返回的键会是数据存储区生成的唯一键。

func PutMulti

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

PutMulti 是 Put 的批处理版本。

src 必须满足与 GetMulti 的 dst 参数相同的条件。

func (*Key) AppID

func (k *Key) AppID() string

AppID 会返回键的应用 ID。

func (*Key) Encode

func (k *Key) Encode() string

Encode 会返回适合在 HTML 和网址中使用的键的不透明表示形式。这与 Python 和 Java 运行时兼容。

func (*Key) Equal

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

Equal 会返回用于判断两个键是否相同的布尔值。

func (*Key) GobDecode

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

func (*Key) GobEncode

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

func (*Key) Incomplete

func (k *Key) Incomplete() bool

Incomplete 会返回用于判断键是否未引用存储实体的布尔值。 具体来说,该键的 StringID 和 IntID 是否为零。

func (*Key) IntID

func (k *Key) IntID() int64

IntID 会返回键的整数 ID(可能是 0)。

func (*Key) Kind

func (k *Key) Kind() string

Kind 会返回键的种类(也称为实体类型)。

func (*Key) MarshalJSON

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

func (*Key) Namespace

func (k *Key) Namespace() string

Namespace 会返回键的命名空间。

func (*Key) Parent

func (k *Key) Parent() *Key

Parent 会返回键的父键(可能是 nil)。

func (*Key) String

func (k *Key) String() string

String 返回键的字符串表示形式。

func (*Key) StringID

func (k *Key) StringID() string

StringID 会返回键的字符串 ID(也称为实体名称或键名称,可能是 "")。

func (*Key) UnmarshalJSON

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

KeyRangeCollisionError

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

func (*KeyRangeCollisionError) Error

func (e *KeyRangeCollisionError) Error() string

KeyRangeContentionError

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

func (*KeyRangeContentionError) Error

func (e *KeyRangeContentionError) Error() string

属性

type Property struct {
	// Name is the property name.
	Name string
	// Value is the property value. The valid types are:
	//	- int64
	//	- bool
	//	- string
	//	- float64
	//	- ByteString
	//	- *Key
	//	- time.Time
	//	- appengine.BlobKey
	//	- appengine.GeoPoint
	//	- []byte (up to 1 megabyte in length)
	//	- *Entity (representing a nested struct)
	// 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.
	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 是名称/值对以及一些元数据。 数据存储区实体的内容会加载并保存为一系列属性。一个实体可以具有多个同名的属性,前提是 p.Multiple 在该实体的所有同名属性中均为 true。

func SaveStruct

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

SaveStruct 会将 src 中的属性以属性切片的形式返回。 src 必须是结构体指针。

PropertyList

type PropertyList []Property

PropertyList 会转换 []Property 以实现 PropertyLoadSaver。

func (*PropertyList) Load

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

Load 会将所有提供的属性加载到 l 中, 而不会先将 *l 重置为空切片。

func (*PropertyList) Save

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

Save 会将 l 的所有属性都保存为属性的切片。

PropertyLoadSaver

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

PropertyLoadSaver 可以与属性切片相互转换。

查询

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

Query 表示数据存储区查询。

func NewQuery

func NewQuery(kind string) *Query

NewQuery 为特定的实体类型创建一个新的查询。

空种类意味着返回所有实体(包括由其他 App Engine 功能创建和管理的实体),称为不分类查询。 不分类查询不能包含针对属性值的过滤条件或排序顺序。

func (*Query) Ancestor

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

Ancestor 会返回包含祖先过滤条件的衍生查询。 祖先不应该是 nil。

func (*Query) BatchSize

func (q *Query) BatchSize(size int) *Query

BatchSize 会返回一个衍生查询,以一次性提取提供的结果数。此值应大于零,等于或小于 Limit。

func (*Query) Count

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

Count 返回查询的结果数量。

Count 发出的 API 调用的运行时间和数量与查询的偏移量和限制的总和成线性比例关系。 除非结果计数预计很小,否则最好指定一个限制;不然 Count 将继续运行,直到其完成计数或提供的上下文到期为止。

func (*Query) Distinct

func (q *Query) Distinct() *Query

Distinct 会返回一个衍生查询,该查询将根据投影字段集生成消除了重复的实体。 Distinct 仅用于投影查询。 Distinct 不能与 DistinctOn 一起使用。

func (*Query) DistinctOn

func (q *Query) DistinctOn(fieldNames string) *Query

DistinctOn 会返回一个衍生查询,该查询将根据指定字段集生成消除了重复的实体。Distinct 仅用于投影查询。 字段列表应该是投影字段列表的子集。DistinctOn 不能与 Distinct 一起使用。

func (*Query) End

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

End 会返回具有给定端点的衍生查询。

func (*Query) EventualConsistency

func (q *Query) EventualConsistency() *Query

EventualConsistency 会返回一个衍生查询,此查询最终会返回一致的结果。 它只对祖先查询有影响。

func (*Query) Filter

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

Filter 会返回一个衍生查询,其中包含基于字段的过滤条件。 filterStr 参数必须是字段名称,其后依次是可选空格以及运算符(>、<、>=、<= 或 = 中的一个)。 Filter 使用运算符将字段与提供的值进行比较。 多个过滤条件可通过 AND 运算符连接在一起。

func (*Query) GetAll

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

GetAll 在给定的上下文中运行查询,同时返回与该查询匹配的所有键,并将值附加到 dst。

对于以下类型,dst 的类型必须为 *[]S、*[]*S 或 *[]P:某些结构体类型 S 或某些非接口非指针类型 P(使得 P 或 *P 可以实现 PropertyLoadSaver)。

特殊情况下,*PropertyList 是 dst 的无效类型,即使 PropertyList 是结构体的切片。 PropertyList 会被视为无效,以免在本应传递 *[]PropertyList 时被错误传递。

GetAll 返回的键与添加到 dst 中的实体是一一对应关系。

如果 q 是“仅限于键”查询,GetAll 会忽略 dst 并且仅返回键。

GetAll 发出的 API 调用的运行时间和数量与查询的偏移量和限制的总和成线性比例关系。除非结果计数预计很小,否则最好指定一个限制;不然 Count 将继续运行,直到其收集完结果或提供的上下文到期为止。

func (*Query) KeysOnly

func (q *Query) KeysOnly() *Query

KeysOnly 会返回一个衍生查询,该查询仅生成键,而不是键和实体。 它不能与投影查询一起使用。

func (*Query) Limit

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

限制会返回一个衍生查询,该查询对返回的结果数量设有限制。 负值意味着无限制。

func (*Query) Offset

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

Offset 会返回一个衍生查询,该查询使用的偏移为返回结果之前要跳过的键数。 负值无效。

func (*Query) Order

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

Order 会返回一个衍生查询,该查询使用基于字段的排序顺序。 应用的顺序是添加字段的顺序。默认顺序是升序;要按照降序排序,请在 fieldName 前加上一个减号 (-) 作为前缀。

func (*Query) Project

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

Project 会返回一个衍生查询,该查询仅生成给定字段。 它不能与 KeysOnly 一起使用。

func (*Query) Run

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

Run 将在给定上下文中运行查询。

func (*Query) Start

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

Start 会返回具有给定起点的衍生查询。

TransactionOptions

type TransactionOptions struct {
	// XG is whether the transaction can cross multiple entity groups. In
	// comparison, a single group transaction is one where all datastore keys
	// used have the same root key. Note that cross group transactions do not
	// have the same behavior as single group transactions. In particular, it
	// is much more likely to see partially applied transactions in different
	// entity groups, in global queries.
	// It is valid to set XG to true even if the transaction is within a
	// single entity group.
	XG bool
	// Attempts controls the number of retries to perform when commits fail
	// due to a conflicting transaction. If omitted, it defaults to 3.
	Attempts int
	// ReadOnly controls whether the transaction is a read only transaction.
	// Read only transactions are potentially more efficient.
	ReadOnly bool
}

TransactionOptions 是用于运行事务的选项。