GetAllUserKeysByFilter

GetAllUserKeysByFilter

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

例如,如果我为KeysOnly制作了GetAll函数(像下面的代码一样),我是否还应该初始化用户的struct([]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
}

而且,如果我只想获取直接调用的 key (在此我已经知道namekey,在这种情况下为namekey == username),以检查此 key 是否存在,那么正确的方法是什么?

现在我喜欢这样:
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
}

但是由于我只关心找出用户 key 是否存在,是否可以将其转换为便宜的价格?

也许将GetAllUserKeysByFilterLimit == 1一起使用会更便宜?

最佳答案

查询/获取运营成本

Get操作(通过键获取)的成本为1个读操作(且操作量不小)。就成本而言,是否有实际实体并不重要:两者都会使您花费1个读操作。 “困难”部分是找到 key 的实体,或者发现没有这样的实体,返回结果就是“简单”部分。

仅键查询的成本是每个结果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()目标参数将被忽略(不使用),仅返回值是有用的,正是这样:结果键片:



因此,基本上您的解决方案也可以使用,但不会使用users slice 。您的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 slice 。

09-04 14:52