具有可选计数的Golang数据存储查询

具有可选计数的Golang数据存储查询,go,google-cloud-datastore,google-cloud-platform,Go,Google Cloud Datastore,Google Cloud Platform,我对golang上的数据存储查询有一些奇怪的问题。查询执行得很好,但是在提取总数(cli.Count())时,每次都会因超时而失败。有人能解释一下我是否做错了什么,或者是否有正确的方法来做这件事吗?奇怪的是,它在查询计数上失败了,我不明白为什么,我也尝试过创建一个新的查询并初始化一个新的客户机,但两者都不起作用 // GetListByID provides an iterative list of all items filtered by ID. func GetListByID(theID

我对golang上的数据存储查询有一些奇怪的问题。查询执行得很好,但是在提取总数(cli.Count())时,每次都会因超时而失败。有人能解释一下我是否做错了什么,或者是否有正确的方法来做这件事吗?奇怪的是,它在查询计数上失败了,我不明白为什么,我也尝试过创建一个新的查询并初始化一个新的客户机,但两者都不起作用

// GetListByID provides an iterative list of all items filtered by ID.
func GetListByID(theID, limit, offset int) ([]Item, int, error) {
    var itemList []Item
    cli, ctx, err := getClient()
    if err != nil {
        return itemList, 0, err
    }
    if limit <= 0 {
        limit = 20
    }

    q := datastore.NewQuery("SomeKind").Filter("MasterID = ", theID)
    ql := q.Limit(limit).Offset(offset)
    _, err = cli.GetAll(ctx, ql, &itemList)
    if err != nil {
        return itemList, 0, err
    }
    if len(itemList) < limit && offset == 0 {
        return itemList, len(itemList), nil
    }
    total, err := cli.Count(ctx, q)

    return itemList, total, err
}
//GetListByID提供了一个迭代列表,列出了按ID筛选的所有项。
func GetListByID(theID,limit,offset int)([]项,int,error){
var itemList[]项
cli,ctx,err:=getClient()
如果错误!=零{
返回项目列表,0,错误
}

if limit注意:云数据存储没有服务器端的
count
聚合。这一点很重要,因为它决定了客户端如何实现
count
等功能

首先,您的代码可能没有执行您认为的操作。
total,err:=cli.Count(ctx,q)
不是从已经执行的查询返回计数,而是接受您的查询,将其设置为仅密钥,然后发出一个新调用以检索所有这些密钥。然后,它根据需要使用游标分页并统计所有结果

你可以看到

抵消 偏移量-与游标不同(应切换到使用游标),偏移不能仅从上次查询停止的位置恢复。要处理偏移,云数据存储需要手动计算与查询匹配的实体数,然后恢复。这意味着函数的每次调用都会在处理新实体之前重新处理所有进行中的实体-一个典型的(N^2)算法

再次:切换到游标:D

这实际上与超时的原因有关(本例中为无限循环)。
Count
的实现保留了偏移量。这取决于您拥有的实体数量和调用函数的方式,可能会变得非常大

这就引出了最终的答案:

计数 编写此问题时可用的Go客户端已损坏。我只是查看了提交历史记录,发现它直到最近才正确处理偏移量和跳过结果。这将导致它不断向云数据存储发出查询,但没有取得进展(只是尝试跳过偏移量的第一个实体)。然后,计数函数将永远不会返回,因为它将继续调用
nextbatch()
,从未取得任何进展

这已通过以下提交在6月初修复:


如果你得到了新版本的Go客户端,你就不应该再有这种无限循环的问题了。

答案实际上是我所期望的,有一个bug最近由OkDave在github上解决了(我提交了一个问题),此处有链接:。我很抱歉忘记返回此处更新答案,我非常感谢您提供的详细信息,因为它解释了许多大多数人可能会错过的事情。出于我的需要,我不想使用游标,因为它会破坏已实现的功能。我期待与selec类似的东西t第50-100项,当再次执行查询时,第50-100项不应与第二次查询前插入数据库的其他项相同。有理由使用游标,也有理由不使用……在我的情况下,我不需要它。问题更多地与已修复的计数有关。

什么是错误您收到的确切错误消息是什么?