【问题标题】:Datastore KeysOnly pricing & implementation in GoGo 中的 Datastore KeysOnly 定价和实施
【发布时间】:2017-09-28 17:28:17
【问题描述】:

我知道 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 == 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 一起使用会更便宜?

【问题讨论】:

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


    【解决方案1】:

    查询/获取运营成本

    Get 操作(按键获取)的成本是 1 个读取操作(并且不是小操作)。密钥是否存在实际实体在成本方面并不重要:两者都将花费您 1 个读取操作。 “困难”部分是找到键的实体,或者发现没有这样的实体,返回结果是“容易”部分。

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

    为了完整起见,“正常”查询(意味着不是仅键)的成本是每个返回实体的 1 个读取操作 + 1 个读取操作。

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

    所以用limit = 1 调用GetAllUserKeysByFilter()理论上花费更多:它花费1 个读取操作和1 个小操作。但由于小型操作是免费的(不需要真钱),它们基本上是相等的。但是要知道Get() 操作(按键)可能会更快,除非您的实体很大。如果您的实体很大,请使用带有 limit = 1 的仅键查询。如果您的实体很小,Get() 很可能会更快(衡量它是否对您很重要)。

    关于查询费用的一些信息可以在这个页面上找到:Datastore Queries

    仅键查询示例

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

    如果 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
    }
    

    附:如果您想将 GetAllUserKeysByFilter() 用于纯键查询和普通查询,您可以继续这样做,但您还应该返回 users 切片。

    【讨论】:

    • 非常感谢,真的很感激 :)!.. 我也能感觉到只有键的功能有些不对劲.. 我想通过让相同的功能可用来变得“聪明”使用 keysonly 和常规 getall 查询(最初有一个用于 keysonly 的过滤器,它会添加 query = query.KeysOnly() 但感觉不对.. PS:毫无疑问,你是我最喜欢的 SO 用户 :)
    • @fisker 基本上你可以继续使用你原来的 GetAllUserKeysByFilter() 来进行仅键查询和普通查询(只是 users 切片不会用于仅键查询),但是你应该还返回 users 切片。稍微更新了答案。
    • 非常感谢,非常感谢 :)!
    猜你喜欢
    • 2015-02-24
    • 1970-01-01
    • 2019-11-18
    • 2014-04-20
    • 1970-01-01
    • 1970-01-01
    • 2021-09-22
    • 2014-06-26
    • 1970-01-01
    相关资源
    最近更新 更多