AppEngine数据存储区:分层查询

时间:2016-09-20 03:02:58

标签: google-app-engine go google-cloud-datastore

如果您正在处理大多数密钥都有祖先的记录层次结构,那么在检索叶子之前是否必须创建所有密钥的链?

示例(在Go中):

rootKey = datastore.NewKey(ctx, "EntityType", "", id1, nil) secondGenKey = datastore.NewKey(ctx, "EntityType", "", id2, rootKey) thirdGenKey = datastore.NewKey(ctx, "EntityType", "", id3, rootKey)

如何获得thirdGenKey描述的记录而不必声明其上方层级的所有级别的密钥?

2 个答案:

答案 0 :(得分:2)

为了获得单个实体,其密钥必须是全局唯一的 - 这通过每个实体密钥在其实体组中是唯一的来强制执行。由于这个原因,祖先路径形成了实体键的固有部分。

因此,获得具有强一致性的单个实体的唯一方法是指定其祖先路径。这可以通过get-by-key或ancestor查询来完成。

如果您不了解完整的祖先路径,您唯一的选择是查询实体的属性,但请记住:

  • 这在您的应用程序中可能不是唯一的
  • 您将受到最终的一致性。

答案 1 :(得分:1)

补充tx802的回答:

如果您想按密钥加载实体,则需要其密钥。如果键是具有父键的键,则为了形成/创建键,还需要先创建父键。父键键的一部分,就像数字ID或字符串名称一样。

从实现角度来看:datastore.Key是一个结构:

type Key struct {
    kind      string
    stringID  string
    intID     int64
    parent    *Key
    appID     string
    namespace string
}

为了构造一个具有父级的Key,您必须以递归方式构造父键。如果你发现它总是创建密钥层次结构太冗长,你可以为它创建一个辅助函数。

为简单起见,我们假设所有密钥都使用相同的实体名称,我们只使用数字ID。它可能看起来像这样:

func createKey(ctx context.Context, entity string, ids ...int) (k *datastore.Key) {
    for _, id := range ids {
        k = datastore.NewKey(ctx, entity, "", id, k)
    }
    return
}

使用此辅助函数,您的示例将简化为:

k2 := createKey(ctx, "EntityType", id1, id2)
k3 := createKey(ctx, "EntityType", id1, id3)