php - AWS SDK CloudSearch 分页

标签 php amazon-web-services pagination amazon-cloudsearch

我正在使用 PHP AWS SDK 与 CloudSearch 通信。根据this post ,分页可以通过 cursorstart 参数完成。但是当你有超过 10,000 次点击时,你不能使用 start

当使用 start 时,我可以指定 ['start' => 1000, 'size' => 100] 直接转到第 10 页。
如何使用 cursor 到达第 1000 页(或任何其他随机页面)?也许有什么方法可以计算这个参数?

最佳答案

我会喜欢有更好的方法,但是这里...

我发现游标的一件事是,当在同一数据集上搜索时,它们会为重复的搜索请求返回相同的值,因此不要将它们视为 session 。虽然您的数据没有更新,但您可以有效地缓存分页的各个方面以供多个用户使用。

我想出了这个解决方案,并用 75,000 多条记录对其进行了测试。

1) 确定您的起点是否低于 10k 限制,如果是,则使用非光标搜索,否则在超过 10K 时,首先使用 initial 执行搜索 游标和大小为 10K 并返回 _no_fields。这给出了我们的起始偏移量,no 字段加快了我们必须消耗的数据量,无论如何我们都不需要这些 ID

2) 计算出您的目标偏移量,并计划需要多少次迭代才能将光标定位在您的目标结果页面之前。然后,我使用我的请求作为缓存哈希来迭代和缓存结果。

对于我的迭代,我从 10K block 开始然后将大小减小到 5k 然后 1k block ,因为我开始“更接近”目标偏移量,这意味着后续分页正在使用更接近最后一个 block 的前一个游标.

例如,这可能是这样的:

  • 获取 10000 条记录(初始光标)
  • 获取 5000 条记录
  • 获取 5000 条记录
  • 获取 5000 条记录
  • 获取 5000 条记录
  • 获取 1000 条记录
  • 获取 1000 条记录

这将帮助我到达 32,000 偏移量标记附近的 block 。如果我需要达到 33,000,我可以使用我的缓存结果来获取将返回前一个 1000 的游标,并从该偏移量重新开始...

  • 获取 10000 条记录(缓存)
  • 获取 5000 条记录(缓存)
  • 获取 5000 条记录(缓存)
  • 获取 5000 条记录(缓存)
  • 获取 5000 条记录(缓存)
  • 获取 1000 条记录(缓存)
  • 获取 1000 条记录(缓存)
  • 获取 1000 条记录(使用缓存游标工作)

3) 现在我们位于您的目标结果偏移量的“附近”,您可以开始将页面大小指定到您的目标之前。然后执行最终搜索以获得实际的结果页。

4) 如果您在索引中添加或删除文档,您将需要一种机制来使之前缓存的结果失效。我通过存储上次更新索引的时间戳并将其用作缓存 key 生成例程的一部分来完成此操作。

重要的是缓存方面,您应该构建一个使用请求数组作为缓存哈希键的缓存机制,以便轻松创建/引用它。

对于非种子缓存,此方法但是如果您可以预热缓存并且仅在索引文档发生更改时使其过期(然后再次预热),您的用户将无法分辨。

这个代码创意适用于每页 20 个项目,我很乐意研究这个,看看我如何才能更智能/更高效地编写代码,但概念就在那里......

// Build $request here and set $request['start'] to be the offset you want to reach

// Craft getCache() and setCache() functions or methods for cache handling.

// have $cloudSearchClient as your client

if(isset($request['start']) === true and $request['start'] >= 10000)
{
  $originalRequest = $request;
  $cursorSeekTarget = $request['start'];
  $cursorSeekAmount = 10000; // first one should be 10K since there's no pagination under this
  $cursorSeekOffset = 0;
  $request['return'] = '_no_fields';
  $request['cursor'] = 'initial';
  unset($request['start'],$request['facet']);
  // While there is outstanding work to be done...
  while( $cursorSeekAmount > 0 )
  {
    $request['size'] = $cursorSeekAmount;
    // first hit the local cache
    if(empty($result = getCache($request)) === true)
    {
      $result = $cloudSearchClient->Search($request);
      // store the results in the cache
      setCache($request,$result);
    }
    if(empty($result) === false and empty( $hits = $result->get('hits') ) === false and empty( $hits['hit'] ) === false )
    {
      // prepare the next request with the cursor
      $request['cursor'] = $hits['cursor'];
    }
    $cursorSeekOffset = $cursorSeekOffset + $request['size'];
    if($cursorSeekOffset >= $cursorSeekTarget)
    {
      $cursorSeekAmount = 0; // Finished, no more work
    }
    // the first request needs to get 10k, but after than only get 5K
    elseif($cursorSeekAmount >= 10000 and ($cursorSeekTarget - $cursorSeekOffset) > 5000)
    {
      $cursorSeekAmount = 5000;
    }
    elseif(($cursorSeekOffset + $cursorSeekAmount) > $cursorSeekTarget)
    {
      $cursorSeekAmount = $cursorSeekTarget - $cursorSeekOffset;
      // if we still need to seek more than 5K records, limit it back again to 5K
      if($cursorSeekAmount > 5000)
      {
        $cursorSeekAmount = 5000;
      }
      // if we still need to seek more than 1K records, limit it back again to 1K
      elseif($cursorSeekAmount > 1000)
      {
        $cursorSeekAmount = 1000;
      }
    }
  }
  // Restore aspects of the original request (the actual 20 items)
  $request['size'] = 20;
  $request['facet'] = $originalRequest['facet'];
  unset($request['return']); // get the default returns
  if(empty($result = getCache($request)) === true)
  {
    $result = $cloudSearchClient->Search($request);
    setCache($request,$result);
  }
}
else
{
  // No cursor required
  $result = $cloudSearchClient->Search( $request );
}

请注意,这是使用自定义 AWS 客户端而不是官方 SDK 类完成的,但请求和搜索结构应该是可比较的。

关于php - AWS SDK CloudSearch 分页,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25971423/

相关文章:

javascript - Java 脚本未在 Wordpress 页面上执行(这是代码中的拼写错误)

php - 如何通过使用 php、javascript、wsdl 调用 Web 服务来发送电子邮件?

php - 如何使用 Laravel 框架更新 MySQL 中的 json 数据?

android - 我应该选择什么 AWS 开发工具包?

amazon-web-services - 如何使用 AWS CLI 在同一行中列出所有具有名称、状态、实例大小和 AZ 的实例

android - 在 android 中滚动时使用改造从 API 获取下 10 个项目的分页

javascript - 数据表分页隐藏 1 2 3 页按钮,仅具有下一个 - 上一个按钮

ios - 处理 Facebook 用户照片的分页

php - 使用 sql WHERE > 'value' 语句有困难

bash - Kubernetes 部署 : preStop does not execute aws commands