我知道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 是否存在,是否可以将其转换为便宜的价格?
也许将
GetAllUserKeysByFilter
与Limit == 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 。