Datastore KeysOnly定价& Go

时间:2017-09-28 17:28:17

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

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

例如,如果我为KeysOnly创建一个GetAll函数(如下所示),我是否应该初始化用户结构([]User)?

func GetAllUserKeysByFilter(ctx context.Context, filters ...UserFilter) ([]*datastore.Key, error) {
    var users []User
    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, &users)
    if err != nil {
        return nil, err
    }
    return keys, nil
}

此外,如果我只想获得直接调用的密钥(我已经知道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
}

但是它可以以某种方式转换成更便宜,因为我只关心找出用户密钥是否存在?

GetAllUserKeysByFilterLimit == 1一起使用可能会更便宜吗?

1 个答案:

答案 0 :(得分:2)

查询/获取运营成本

Get操作的成本(按键获取)是1读操作(并且没有小操作)。是否存在密钥的实际实体在成本方面无关紧要:两者都将花费您1读取操作。 "硬"部分是找到密钥的实体,或者发现没有这样的实体,返回的结果是" easy"一部分。

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

为了完整性,正常情况下的费用为"查询(意思不仅仅是键)是每个返回实体的1个读操作+ 1个读操作。

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

因此,使用GetAllUserKeysByFilter()调用limit = 1 理论上会花费更多:它需要1次读取操作和1次小操作。但由于小型业务是免费的(成本没有真钱),它们基本上是平等的。但要知道,除非您的实体很大,否则Get()操作(按键)可能会更快。如果您的实体很大,请使用仅限密钥查询limit = 1。如果您的实体很小,Get()很可能会更快(衡量一下,如果它对您来说很重要)。

有关查询费用的一些信息,请访问此页面:Datastore Queries

仅限密钥查询示例

您对仅键查询的实现不必要地复杂。当您执行仅密钥查询时,dst目标参数Query.GetAll()被省略(未使用),只有返回值才有用,这正是:结果键的切片:

  

如果q是“仅限密钥”查询,则GetAll会忽略dst并仅返回密钥。

所以基本上你的解决方案也有效,但不会使用users切片。您的GetAllUserKeysByFilter()函数应如下所示:

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
}

P.S。如果您想为仅使用密钥和普通查询重用GetAllUserKeysByFilter(),您可以继续这样做,但是您还应该返回users切片。