【问题标题】:Pagination with Dynamodb in web application在 Web 应用程序中使用 Dynamodb 进行分页
【发布时间】:2014-06-24 02:02:40
【问题描述】:

我的数据库中有大约 5000 多个视频,我创建了一个页面 http://mysite.com/videos 来列出所有视频。现在我正在实施分页,以便每页仅列出 20 个视频。例如

http://mysite.com/videos?page=1 显示前 20 个视频,http://mysite.com/videos?page=2 显示后 20 个视频。

我在选择实现分页的最佳方法时遇到问题。我想在每次执行新页面时使用 table.scan() ,然后根据 Python 代码的一些逻辑只选择需要的。但这似乎相当昂贵。

我正在使用带有 boto 库的 Python / Django。

【问题讨论】:

    标签: python django amazon-web-services boto amazon-dynamodb


    【解决方案1】:

    在 Dynamo 中,您可以通过设置限制来执行查询。来自文档:

    http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html

    你可以阅读:

    ExclusiveStartKey 
    

    第一个项目的主键 操作将评估。使用返回的值 上一个操作中的 LastEvaluatedKey。

    ExclusiveStartKey 的数据类型必须是字符串、数字或二进制。 不允许设置数据类型。

    Type: String to AttributeValue object map
    
    Required: No
    

    Limit
    

    要评估的最大项目数(不一定是匹配项目的数量)。如果 Amazon DynamoDB 处理的数量 在处理结果时项目达到限制,它会停止 操作并返回直到该点的匹配值,以及 LastEvaluatedKey 在后续操作中应用,这样就可以 从你离开的地方继续。另外,如果处理的数据集大小 在 Amazon DynamoDB 达到此限制之前超过 1 MB,它会停止 操作并返回匹配值直到限制,以及 LastEvaluatedKey 在后续操作中应用以继续 手术。有关更多信息,请参阅亚马逊中的查询和扫描 DynamoDB 开发人员指南。

    Type: Number
    
    Required: No
    

    您没有提供有关表的键结构的任何信息。但是,方法是查询表中与您的键匹配的元素(如果合适,还有范围键),限制设置为 20。 结果,您将收到一个“LastEvaluatedKey”,您必须将其用于下一个查询,同样限制设置为 20。

    【讨论】:

      【解决方案2】:

      这里有一些选项:

      1. 您可以在应用程序启动时预加载所有视频对象,然后按照您想要的方式进行内存分页。 5000 多个对象应该没什么大不了的。
      2. 您可以获取第一页,然后异步获取其余页面(通过扫描),然后再次在内存中进行分页。
      3. 您可以创建一个索引表,该表将为每个页面存储一个条目,其中包含每个视频的 id-s,然后获取您调用的页面的视频: 3.1 通过page id获取页面(简单get操作)。这将包含应该在该页面上的视频 ID 列表 3.2 通过multi-get操作获取3.1中的所有视频

      对于类似的用例,我们通过 Javascript 对象加载所有元数据,并从那里进行分页和排序,最终结果对用户来说非常好(快速且响应迅速)。同样,我们正在使用获取第一页然后再次获取整个内容的技巧(因为 DynamoDB 目前不支持游标)

      【讨论】:

        【解决方案3】:

        极限不是你想的那样。这是我的建议:

        使用 DynamoDBMapper 发出一个

        numRows = mapper.count(<SomeClass>.class, scanExpression) 
        

        有效地获取表中的行数。

        然后运行一个

        PaginatedScanList<FeedEntry> result = mapper.scan(<SomeClass>.class, scanExpression);
        

        获取列表 - 这里的关键是 PaginatedScanList 是延迟加载的。注意不要对结果执行 .size() ,因为这将加载所有行。只需使用 .get() 仅加载您需要的行。

        使用

        遍历分页扫描列表
        offset = startPage * pageSize
        ArrayList<SomeClass> list = new ArrayList<SomeClass>()
        for (i = 0 ... pageSize) 
        list.add(result.get( offset + i))
        

        检查越界等。希望对您有所帮助。

        【讨论】:

          猜你喜欢
          • 2017-08-03
          • 2010-10-25
          • 2012-10-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-06-16
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多