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

Golang Datastore Query with optional count

我在 golang 上查询数据存储时遇到了一些奇怪的问题。查询执行得很好,但是当涉及到总计 (cli.Count()) 时,它每次都会因超时而失败。有人可以解释我是否做错了什么或者是否有正确的方法来做到这一点?奇怪的是它在查询计数上失败了,我不明白为什么,我也尝试创建一个 NewQuery 并初始化一个新客户端,但都不起作用。

// 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
}

请注意,它不会 运行 在 appengine 上。它 运行 在 AWS 和数据中心的实例上。 (不要问)

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

等功能

首先,您的代码可能没有按照您的想法运行。

total, err := cli.Count(ctx, q) 不会从您已执行的查询中返回计数,它会接受您的查询,使其成为仅键,然后发出新调用以检索所有这些键。然后它会根据需要使用游标进行分页并对所有结果进行计数。

你可以看到 implementation here on gitHub

偏移量

偏移量 - 与游标(您应该切换到使用)不同,偏移量仅通过从上次中断的查询处恢复而不起作用。要处理偏移量,Cloud Datastore 需要手动计算 offset 个与您的查询匹配的实体,然后恢复。这意味着您的函数的每次调用都会在处理新实体之前重新处理所有正在进行的实体 - 经典的 O(N^2) 算法。

再一次:切换到游标 :D

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

这使我们得出最终答案:

计数

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

这是在 6 月初通过以下提交修复的:https://github.com/GoogleCloudPlatform/gcloud-golang/commit/0bf7a0795c591c70a17505c1123bc3ef3d30f426

如果您获得了新版本的 Go 客户端,您应该不会再遇到这个无限循环问题了。

答案实际上是按照我的预期去做的,OkDave 最近在 github 上解决了一个错误(我提交了一个问题),link 可以在这里找到:https://github.com/GoogleCloudPlatform/gcloud-golang/issues/268.我很抱歉忘记回到这里更新答案,我非常感谢你的详细信息,因为它解释了很多大多数人可能实际上错过的事情。出于我的需要,我不想使用游标,因为它会破坏已实现的功能。我期待与 select 项目 50 - 100 类似的内容,当第二次再次执行查询时,项目 50 - 100 不应该与在第二次之前插入数据库的其他项目相同询问。有使用游标的理由,也有不使用游标的理由……在我的情况下,我不想要它。问题与已修复的计数更相关。