我知道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
}
但是它可以以某种方式转换成更便宜,因为我只关心找出用户密钥是否存在?
将GetAllUserKeysByFilter
与Limit == 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
切片。