【问题标题】:How to paginate an aggregation pipeline result in pymongo?如何在 pymongo 中对聚合管道结果进行分页?
【发布时间】:2020-10-26 15:35:26
【问题描述】:

我有一个 Web 应用程序,我在 Mongo 中存储了一些数据,我需要从查找或聚合管道返回分页响应。我使用 Django Rest Framework 和它的分页,它最终只是分割了 Cursor 对象。这对游标无缝工作,但聚合返回 CommandCursor,它没有实现 __getitem__()

cursor = collection.find({})
cursor[10:20] # works, no problem

command_cursor = collection.aggregate([{'$match': {}}])
command_cursor[10:20] # throws not subscriptable error

这背后的原因是什么?有人有CommandCursor.__getitem__() 的实现吗?真的可行吗?

当我只需要一个页面时,我想找到一种不获取所有值的方法。对于大型(100k+ 文档)管道结果,转换为列表然后对其进行切片是不可行的。有一个基于this answer 的解决方法,但这仅适用于前几页,并且最后页​​面的性能迅速下降。

【问题讨论】:

    标签: python mongodb pymongo


    【解决方案1】:

    findaggregate 的 MongoDB 游标以不同的方式发挥作用,因为聚合查询的游标结果是处理数据的结果(在大多数情况下),而查找游标不是这种情况,因为它们是静态的并且因此可以跳过文档并限制在您的意愿范围内。

    您可以将分页器限制添加为聚合管道中的$skip$limit 阶段。

    例如:

    command_cursor = collection.aggregate([
        {
            "$match": {
                # Match Conditions
            }
        },
        {
            "$skip": 10  # No. of documents to skip (Should be `0` for Page - 1)
        },
        {
            "$limit": 10  # No. of documents to be displayed on your webpage
        }
    ])
    

    【讨论】:

      【解决方案2】:

      Mongo 有特定的聚合管道阶段来处理这个问题,例如 $skip$limit,您可以像这样使用:

      aggregation_results = list(collection.aggregate([{'$match': {}}, {'$skip':  10}, {'$limit':  10}]))
      

      特别是您注意到 Pymongo 的 command_cursor 没有实现 __getitem__ 因此常规迭代器语法无法按预期工作。我个人建议不要篡改他们的代码,除非你有兴趣成为他们包的贡献者。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-01-01
        • 2020-10-12
        • 2019-07-12
        • 2017-07-26
        • 1970-01-01
        • 1970-01-01
        • 2016-06-12
        • 2021-12-06
        相关资源
        最近更新 更多