Google app engine 仅数据存储密钥定价&;围棋的实施

Google app engine 仅数据存储密钥定价&;围棋的实施,google-app-engine,go,google-cloud-datastore,Google App Engine,Go,Google Cloud Datastore,我知道KeysOnly查询更便宜,但我想知道我是否正确地实现了它 例如,如果我为KeysOnly(如下所示)创建了一个GetAllfunc,那么我是否仍应该初始化users结构([]User) 此外,如果我只想获取一个直接调用的键(我已经知道namekey,在本例中是,namekey==username),以检查该键是否存在,那么正确的方法是什么 现在我喜欢这样: func GetUserByNameKey(ctx context.Context, key *datastore.Key) (Us

我知道KeysOnly查询更便宜,但我想知道我是否正确地实现了它

例如,如果我为KeysOnly(如下所示)创建了一个
GetAll
func,那么我是否仍应该初始化users结构(
[]User

此外,如果我只想获取一个直接调用的键(我已经知道namekey,在本例中是,
namekey==username
),以检查该键是否存在,那么正确的方法是什么

现在我喜欢这样:

func GetUserByNameKey(ctx context.Context, key *datastore.Key) (User, error) {
    var user User
    err := DatastoreClient().Get(ctx, key, &user)
    if err != nil {
        return user, err
    }
    return user, nil
}
func GetAllUserKeysByFilter(ctx context.Context, filters ...UserFilter)
        ([]*datastore.Key, error) {

    query := datastore.NewQuery("User").KeysOnly()
    for _, filter := range filters {
        if filter.Age != 0 {
            query = query.Filter("Age =", filter.Age)
        }
        if filter.Limit != 0 {
            query = query.Limit(filter.Limit)
        }
    }
    keys, err := DatastoreClient().GetAll(ctx, query, nil)
    if err != nil {
        return nil, err
    }
    return keys, nil
}
但是,由于我只关心用户密钥是否存在,它能否以某种方式转换成更便宜的密钥

使用
GetAllUserKeysByFilter
Limit==1

查询/获取操作成本可能会更便宜 Get操作(按键获取)的成本是1个读取操作(并且没有小的操作)。键是否有一个实际的实体在成本方面并不重要:两者都将花费您1个阅读操作。“困难”部分是找到键的实体,或者发现没有这样的实体,返回的结果是“简单”部分

对于每个结果(对于每个结果键),仅键查询的成本为1个读取操作+1个小操作

为了完整性,对于每个返回的实体,“普通”查询(不仅仅指键)的成本是1个read op+1个read op

示例:返回10个实体的普通查询是11个读取操作。返回10个键的仅键查询是1个读取操作+10个小操作。Get调用是1个read op(无论是否找到并返回实体)

因此,用
limit=1
调用
GetAllUserKeysByFilter()
理论上会花费更多:它需要1次读取操作和1次小操作。但由于小规模运营是免费的(不需要真正的资金),它们基本上是平等的。但是要知道,除非您的实体很大,否则
Get()
操作(按键)可能会更快。如果实体较大,请使用带有
limit=1
的仅关键帧查询。如果您的实体很小,
Get()
很可能会更快(如果它对您有影响,请进行测量)

有关查询成本的一些信息可在此页面上找到:

仅键查询示例 您对仅密钥查询的实现是不必要的复杂。当您执行仅限键查询时,的
dst
destination参数被省略(未使用),只有返回值是有用的,即:结果键的切片:

如果q是“仅键”查询,则GetAll忽略dst并仅返回键

因此,基本上您的解决方案也可以工作,但不会使用
users
切片。您的
GetAllUserKeysByFilter()
函数应该如下所示:

func GetUserByNameKey(ctx context.Context, key *datastore.Key) (User, error) {
    var user User
    err := DatastoreClient().Get(ctx, key, &user)
    if err != nil {
        return user, err
    }
    return user, nil
}
func GetAllUserKeysByFilter(ctx context.Context, filters ...UserFilter)
        ([]*datastore.Key, error) {

    query := datastore.NewQuery("User").KeysOnly()
    for _, filter := range filters {
        if filter.Age != 0 {
            query = query.Filter("Age =", filter.Age)
        }
        if filter.Limit != 0 {
            query = query.Limit(filter.Limit)
        }
    }
    keys, err := DatastoreClient().GetAll(ctx, query, nil)
    if err != nil {
        return nil, err
    }
    return keys, nil
}

另外,如果您想将
GetAllUserKeysByFilter()
重复用于仅键查询和普通查询,您可以继续这样做,但是您还应该返回
users
切片。

非常感谢,非常感谢:)!。。我也能感觉到只有按键的功能出了问题。。我曾想通过让同一个函数同时适用于keysonly和常规getall查询而变得“聪明”(最初有一个keysonly过滤器,它会添加
query=query.keysonly()
,但感觉不对..PS:毫无疑问,你是我最喜欢的SO用户:)@fisker基本上,您可以继续将原始的
GetAllUserKeysByFilter()
用于仅键查询和普通查询(仅
用户
切片将不用于仅键查询),但您还应该返回
用户
切片。稍微更新了答案。非常感谢,非常感谢:)!