google-app-engine - 批量查询分页?是否可以从数据存储中批量获取并获取游标?

标签 google-app-engine go google-cloud-datastore

我目前正在从数据存储中请求 20 个条目,使用游标将这些返回给用户,如果用户要求更多条目,请使用游标作为新的开始并请求接下来的 20 个条目。

代码看起来像

q := datastore.NewQuery("Item").
    Limit(limit)

if cursor, err := datastore.DecodeCursor(cursor); err == nil {
    q = q.Start(cursor)
}

var is []Item
t := q.Run(c)
for {
    var i Item
    _, err := t.Next(&i)
    if err == datastore.Done {
        break
    }

    is = append(is, i)
}

如果重要的话,这里是完整的代码:https://github.com/koffeinsource/kaffeeshare/blob/master/data/appengine.go#L23

使用带有 append 的循环看起来是一种反模式,但我没有看到使用 GetMulti/ 时获取游标的方法GetAll 还是我遗漏了什么?

我确实希望在用户查询数据存储时添加数据,因此偏移量可能会产生重复的结果。在这种情况下,我应该关心批处理获取吗?

最佳答案

您的方法非常好,事实上,这是 AppEngine 上最好的方法。

通过设置开始游标查询后续实体不会给您重复的结果,如果插入了新记录,例如第一个。

为什么?因为游标包含编码的最后返回的实体的键,而不是先前返回的实体的数量。

因此,如果您设置游标,数据存储将开始列出并返回游标中编码的键之后的实体。如果保存了光标之后的新实体,则到达时将返回该实体。

同时使用 forappend() 是最好的方法。您可以通过事先创建足够大的 slice 来对其进行一些优化:

var is = make([]Item, 0, limit)

但请注意,我是故意用 0 长度和 limit 容量来实现的:不能保证有足够的实体来填充整个 slice 。

另一个优化是将其分配为 limit 长度:

var is = make([]Item, limit)

并且当到达datastore.Done时,如果没有填满则重新分片,例如:

for idx := 0; ; idx++ {
    var i Item
    _, err := t.Next(&i)
    if err == datastore.Done {
        if idx < len(is) {
            is = is[:idx] // Reslice as it is not filled fully
        }
        break
    }

    is[idx] = i
}

批量操作

GetMulti, PutMulti and DeleteMulti are batch versions of the Get, Put and Delete functions. They take a []*Key instead of a *Key, and may return an appengine.MultiError when encountering partial failure.

批处理操作不能替代查询。例如,GetMulti 要求您已经准备好要获取完整实体的所有键。因此,这些批处理操作没有光标的感觉。

批处理操作会返回所有请求的信息(或执行所有请求的操作)。没有实体或操作的顺序可以/可以终止并在以后继续。

查询和批处理操作是不同的。您不必担心查询和游标性能。他们做得很好,重要的是,他们(数据存储)的扩展性很好。游标不会减慢查询的执行速度,带有游标的查询运行速度与没有游标的查询一样快,而且之前返回的实体不会影响查询执行时间:是否运行查询无关紧要没有游标或有游标是您在获得一百万个实体后获得的(这只有通过多次迭代才有可能)。

关于google-app-engine - 批量查询分页?是否可以从数据存储中批量获取并获取游标?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31902903/

相关文章:

javascript - 一名或多名参与者未能使用 google 仪表板绘制()

google-app-engine - AppEngine/Go : urlfetch vs http. 获取等

go - 在golang中的if条件的基础上重写一个变量类型

linux - 避免解析 Xrandr 输出

python - 如何在 GAE 上最好地设计日期/地理邻近查询?

python - 运行 Google App Engine Python 的本地数据存储是否有任何限制?

java - 获取云存储中的文件列表 (Java)

go - 不能使用函数(类型 func())作为参数类型

python - 使用 GAE + ndb 进行配对

java - 在数据存储中使用 Blob,但 Android 不知道命名空间