Google Cloud数据存储分页

时间:2017-04-09 19:25:20

标签: google-cloud-datastore

我们将数据存储在Google Cloud Datastore中。我们希望为用户提供API。 我们的API分页规范与github API相同。我们希望用户使用页面参数。

分页规范

e.g.

Link: <https://api.github.com/search/code?q=addClass+user%3Amozilla&page=15>; rel="next",
  <https://api.github.com/search/code?q=addClass+user%3Amozilla&page=34>; rel="last",
  <https://api.github.com/search/code?q=addClass+user%3Amozilla&page=1>; rel="first",
  <https://api.github.com/search/code?q=addClass+user%3Amozilla&page=13>; rel="prev"

https://developer.github.com/guides/traversing-with-pagination/

API

End-Users <--- Backend Code (PHP) <--- Google Cloud Datastore

如您所知,Google Cloud Datastore建议使用游标来提高性能和成本。但我们不希望最终用户使用游标。最终用户是否可能使用整数页码而不是游标?后端使用光标?

我们使用Google的PHP客户端。

https://github.com/google/google-api-php-client-services

3 个答案:

答案 0 :(得分:4)

我相信你可以通过使用GQL来获得类似OFFSET的东西,但是这样的操作会花费你很多钱(相当于LIMIT 1000, 10会算作 1,010次读取 - 不仅仅是你实际回来的10个。)

降低分页OFFSET的费用

假设您的页面大小为10个项目并且用户要求跳转到第5页。您需要查询前40个实体,获取光标并再次运行查询,现在提供光标并限制为10

建议您在第一个查询中使用keys_only=True进行提取。这样你就可以:

答案 1 :(得分:2)

Google建议使用游标,并在其文档中有一个示例。 https://cloud.google.com/datastore/docs/concepts/queries#cursors_limits_and_offsets

const pageSize = 5
query := datastore.NewQuery("Tasks").Limit(pageSize)
if cursorStr != "" {
        cursor, err := datastore.DecodeCursor(cursorStr)
        if err != nil {
                log.Fatalf("Bad cursor %q: %v", cursorStr, err)
        }
        query = query.Start(cursor)
}

// Read the tasks.
var tasks []Task
var task Task
it := client.Run(ctx, query)
_, err := it.Next(&task)
for err == nil {
        tasks = append(tasks, task)
        _, err = it.Next(&task)
}
if err != iterator.Done {
        log.Fatalf("Failed fetching results: %v", err)
}

// Get the cursor for the next page of results.
nextCursor, err := it.Cursor()

答案 2 :(得分:0)

我不确定 GCloud 数据存储区的光标是否可用于用户需要“跳转”到不同页码的分页实现。这是我在项目中实现数据存储分页的方式:

给定一个现有的查询(排序、过滤等),一个“偏移量”(一个数字)和一个“限制”(一个数字)

  1. 使用限制(偏移+限制)运行仅键查询
  2. 将第 1 步中的结果从偏移量(直到结束)切片并将它们映射到 Datastore.KEY
  3. 使用步骤 2 中获得的一组键创建并运行 datastore.get() 查询。

NodeJS 中的代码:

async function paginate(query, offset, limit) {
  let results;
  if (offset > 0) {
    // Get the keys (low cost)
    query.select('__key__');
    query.limit(offset + limit);
    const [keys] = await datastore.runQuery(query);

    const [entities] = await datastore.get(keys.slice(offset).map(k => k[Datastore.KEY]));
    return entities;
  }
  query.limit(limit);
  const [entities] = await datastore.runQuery(query);
  return entities;
}