【问题标题】:Google Cloud datastore pagination谷歌云数据存储分页
【发布时间】:2017-04-09 19:25:20
【问题描述】:

我们将数据存储在 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 建议使用游标来提高性能和成本。但我们不希望最终用户使用光标。是否可能最终用户使用整数页码而不是游标,而游标用于后端?

我们使用谷歌的 PHP 客户端。

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

【问题讨论】:

    标签: google-cloud-datastore


    【解决方案1】:

    我相信您可以通过使用 GQL 获得类似 OFFSET 的内容,但这样的操作会花费您很多钱(执行相当于 LIMIT 1000, 10 的操作将计为 1,010 次读取 - 不是只是你实际返回的 10 个)。

    降低OFFSET 的分页成本

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

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

    【讨论】:

      【解决方案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()
      

      【讨论】:

        【解决方案3】:

        我不确定 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;
        }
        

        【讨论】:

          猜你喜欢
          • 2015-07-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-05-11
          • 1970-01-01
          • 2018-10-11
          • 2019-01-15
          相关资源
          最近更新 更多