简体   繁体   English

使用PHP的AWS DynamoDB分页

[英]Pagination with AWS DynamoDB with PHP

Have someone any idea about Paginating the records from a table. 有人知道从表中分页记录。 Actually I want to create a paginate component in php with DynamoDb. 其实我想在php中使用DynamoDb创建一个paginate组件。

It seems like it is not possible to giving pagination like <first> <prev> 1,2,3, 4 ,5... <next> <last>. 现在看来似乎是不可能给分页像<第一次> <前> 1,2,3,4,5 ... <下> <最后>。

Because Dyanmodb just provide us LIMIT clause by which we can read certain no. 因为Dyanmodb只是提供了我们LIMIT条款,我们可以通过它来阅读某些号码。 of records and we can process next n records by LastEvaluatedKey. 记录,我们可以通过LastEvaluatedKey处理下n个记录。 So if I want to jump directly to 5th page, How is it possible ? 所以,如果我想直接跳到第5页,怎么可能?

As per my understanding we can't display page numbers into the pagination. 根据我的理解,我们无法将页码显示在分页中。 The thing we can do is just read certain limit of records and provide the NEXT link to retrieve next n records. 我们能做的就是读取某些记录限制并提供NEXT链接来检索下n条记录。

Pagination is basic feature of any web application, How can we implement if migrating to cloud database like DynamoDb ? 分页是任何Web应用程序的基本功能,如果迁移到像DynamoDb这样的云数据库,我们如何实现?

Please provide your views and suggestions. 请提供您的意见和建议。 Thanks 谢谢

Yes, you are right, there is no OFFSET in DynamoDB. 是的,你是对的,DynamoDB中没有OFFSET But using only Limit and LastEvaluatedKey , i made this function: 但是只使用LimitLastEvaluatedKey ,我做了这个功能:

public function scan($table, $filter = [], $select = null, $limit = 2)
{
    $page = isset($_GET['page']) ? $_GET['page'] : 0;
    $options = [
        'TableName' => $table,
        'Count' => true,
    ];

    if (!empty($limit)) {
        $options['Limit'] = $limit;
    }

    if (!is_null($select)) {
        $options['Select'] = $select;
    }

    if (!empty($filter)) {
        $options['ScanFilter'] = $filter;
    }

    $results = $results = $this->_client->scan($options);

    while ($page > 0 && isset($results['LastEvaluatedKey'])) {
        $results = $results = $this->_client->scan($options);
        $options['ExclusiveStartKey'] = $results['LastEvaluatedKey'];
        $page--;
    }

    return $results;
}

$this->_client refers to DynamoDb client object. $this->_client是指DynamoDb客户端对象。
Basically i loop through all entries with LastEvaluatedKey till i reach needed page. 基本上我用LastEvaluatedKey循环遍历所有条目,直到我到达所需的页面。
To get total entries in table, call $this->scan($this->tableName(), [], null, null)['Count']; 要获取表中的总条目,请调用$this->scan($this->tableName(), [], null, null)['Count']; (that is - without any search criteria and without pagination, just as in normal pagination function). (即 - 没有任何搜索条件且没有分页,就像在正常的分页功能中一样)。

To add to @Justinas' answer, Dynamo will have pretty horrible performance for pagination if random access (ie. jump to an arbitrary page) is desired. 为了增加@Justinas的答案,如果需要随机访问(即跳转到任意页面),Dynamo将具有相当可怕的分页性能。 However, if you only do next page and previous page, you could pass around the LastEvaluatedKey and keep the overhead due to scanning to a minimum. 但是,如果您只执行下一页和上一页,则可以传递LastEvaluatedKey并将扫描的开销保持在最低限度。

As stated in the comments, you should definitely cache the results as much as possible. 如评论中所述,您应该尽可能地缓存结果。 At a minimum, the LastEvaluatedKey results could be cached so that they don't need to be recomputed for each paging request when users page through the results. 至少可以缓存LastEvaluatedKey结果,以便在用户翻阅结果时不需要为每个分页请求重新计算它们。 Here's an example of what I mean: 这是我的意思的一个例子:

Say you have a table that has a schema like this, where CommentID is the hash-key. 假设您有一个具有这样的模式的表,其中CommentID是散列键。

 CommentID | Author | Comment | ...
-----------+--------+---------+------------
    1      | Joe    | Foo     | ...
    2      | Joe    | Bar     | ...
    3      | John   | Baz     | ...
    4      | Joe    | FooBar  | ...
    5      | Jane   | BooBaz  | ...
    6      | Joesie | Blah    | ...
    7      | Johnny | Blahaha | ...

When you start paging, say you request 3 comments per page, you will get the first page results and the LastEvaluatedKey = 3 ; 当您开始分页时,假设您每页请求3条评论,您将获得第一页结果和LastEvaluatedKey = 3 ; Then if you make a second scan request, for page 2, using ExclusiveStartKey=3 you will get LastEvaluatedKey = 6 ; 然后,如果您针对第2页发出第二个扫描请求,则使用ExclusiveStartKey=3您将获得LastEvaluatedKey = 6 ; To get page 3 you would make another scan using LastEvaluatedKey = 6 .. and so on. 要获得第3页,您将使用LastEvaluatedKey = 6进行另一次扫描..依此类推。

You can see that without any kind of caching, to get Page 3 you are performing three scans (two of which would have been repeated if you also requested pages 1 and two prior to page 3). 您可以看到,在没有任何缓存的情况下,您要执行三次扫描(如果您还请求第3页之前的第1页和第2页,则会重复其中两次扫描)。 So, my proposed optimization is to store the corresponding keys for each page. 因此,我建议的优化是为每个页面存储相应的键。 You would end up with a map like this: 你最终得到这样的地图:

 Page | Hash-Key
------+----------
   1  |   null
   2  |     3
   3  |     6
  ..  |    ... 

And the values would get filled out as you page through results. 当您翻阅结果时,这些值将被填写。 Now, when a user wants page 3, all you have to do is one scan, using 6 as the ExclusiveStartKey . 现在,当用户想要第3页时,您所要做的就是一次扫描,使用6作为ExclusiveStartKey

Of course you would need a look-up table like this for each page size, and the table would only be accurate until new rows get added (or removed). 当然,对于每个页面大小,您需要一个这样的查找表,并且只有在添加(或删除)新行之前,该表才是准确的。 That said, if you have lots of requests the extra memory needed to store the paging cache would be well worth it. 也就是说,如果你有很多请求,那么存储分页缓存所需的额外内存将非常值得。 All is left then is to set a reasonable expiration for your paging cache, depending on how often new data is added (or removed) in your table.. 剩下的就是为您的分页缓存设置合理的到期时间,具体取决于在表中添加(或删除)新数据的频率。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM