【问题标题】:Easiest way to load documents from MongoDB collection in chunks of 10以 10 个为一组从 MongoDB 集合中加载文档的最简单方法
【发布时间】:2020-05-19 17:59:26
【问题描述】:

我想创建一个应用程序来创建订单,然后将它们加载到列表中。问题是我无法一次加载所有订单。我想按 10 x 10 加载它们。

然而,这在 MongoDB 中看起来很难做到,因为没有像 SQL 中那样的自动 id。我知道如何模拟自动id,但我认为实现这个功能应该更容易。

那么,给定一个 MongoDB 集合,我如何加载文档 10 x 10,从最新的文档开始直到开始?

【问题讨论】:

  • 您可能会使用带有限制和排序的Cursor。你可以找到一些例子here
  • @cubrr 我想我忘了指定我从 REST API 访问东西,所以我不能使用游标,因为它需要保存状态
  • 使用你需要的任何排序选项打开一个batchSize为10的游标,每次处理10个文档时,驱动程序应该自动获取下一批10
  • @Joe 但这样 API 不是 REST,因为我必须维护一个状态。即游标需要保持在服务器上。

标签: node.js mongodb mongoose


【解决方案1】:

您需要按字段对文档进行排序,然后使用 skiplimit 聚合。我们也可以使用facet 聚合来获取记录总数。

这里有详细的解释:

假设您在订单集合中有这 8 个文档。

[
    {
        "_id": "5e390fc33285e463a0799689",
        "customer": "Max",
        "total": 10,
        "orderDate": "2020-02-04T06:31:31.311Z",
        "__v": 0
    },
    {
        "_id": "5e390fd03285e463a079968a",
        "customer": "John",
        "total": 9.2,
        "orderDate": "2020-02-04T06:31:44.190Z",
        "__v": 0
    },
    {
        "_id": "5e390fda3285e463a079968b",
        "customer": "Smith",
        "total": 11.3,
        "orderDate": "2020-02-04T06:31:54.248Z",
        "__v": 0
    },
    {
        "_id": "5e390fdf3285e463a079968c",
        "customer": "Smith",
        "total": 12.3,
        "orderDate": "2020-02-04T06:31:59.993Z",
        "__v": 0
    },
    {
        "_id": "5e390fec3285e463a079968d",
        "customer": "Jimmy",
        "total": 15.6,
        "orderDate": "2020-02-04T06:32:12.336Z",
        "__v": 0
    },
    {
        "_id": "5e390ffd3285e463a079968e",
        "customer": "Wesley",
        "total": 11,
        "orderDate": "2020-02-04T06:32:29.670Z",
        "__v": 0
    },
    {
        "_id": "5e3910163285e463a079968f",
        "customer": "Adam",
        "total": 6.1,
        "orderDate": "2020-02-04T06:32:54.131Z",
        "__v": 0
    },
    {
        "_id": "5e3910213285e463a0799690",
        "customer": "Michael",
        "total": 7.2,
        "orderDate": "2020-02-04T06:33:05.166Z",
        "__v": 0
    }
]

如果我们想分块获取这些文档,我们可以编写如下示例路由:

router.get("/orders", async (req, res) => {
  const page = req.query.pageIndex ? +req.query.pageIndex : 1;
  const limit = req.query.pageSize ? +req.query.pageSize : 10;
  const skip = (page - 1) * limit;

  const result = await Order.aggregate([
    {
      $sort: {
        orderDate: -1
      }
    },
    {
      $facet: {
        totalRecords: [{ $count: "total" }],
        data: [{ $skip: skip }, { $limit: limit }]
      }
    }
  ]);
  res.send(result);
});

我们在查询字符串中发送 pageIndex 和 pageSize 参数,例如 http://...../orders?pageIndex=1&pageSize=3

当我们使用pageIndex=1pageSize=3时,结果会是这样的:(如您所见,我们还返回记录总数,以便客户端可以构建分页数)

[
    {
        "totalRecords": [
            {
                "total": 8
            }
        ],
        "data": [
            {
                "_id": "5e3910213285e463a0799690",
                "customer": "Michael",
                "total": 7.2,
                "orderDate": "2020-02-04T06:33:05.166Z",
                "__v": 0
            },
            {
                "_id": "5e3910163285e463a079968f",
                "customer": "Adam",
                "total": 6.1,
                "orderDate": "2020-02-04T06:32:54.131Z",
                "__v": 0
            },
            {
                "_id": "5e390ffd3285e463a079968e",
                "customer": "Wesley",
                "total": 11,
                "orderDate": "2020-02-04T06:32:29.670Z",
                "__v": 0
            }
        ]
    }
]

当我们使用pageIndex=2pageSize=3时,结果会是这样的:

[
    {
        "totalRecords": [
            {
                "total": 8
            }
        ],
        "data": [
            {
                "_id": "5e390fec3285e463a079968d",
                "customer": "Jimmy",
                "total": 15.6,
                "orderDate": "2020-02-04T06:32:12.336Z",
                "__v": 0
            },
            {
                "_id": "5e390fdf3285e463a079968c",
                "customer": "Smith",
                "total": 12.3,
                "orderDate": "2020-02-04T06:31:59.993Z",
                "__v": 0
            },
            {
                "_id": "5e390fda3285e463a079968b",
                "customer": "Smith",
                "total": 11.3,
                "orderDate": "2020-02-04T06:31:54.248Z",
                "__v": 0
            }
        ]
    }
]

当我们使用pageIndex=3pageSize=3时,结果会是这样的:

[
    {
        "totalRecords": [
            {
                "total": 8
            }
        ],
        "data": [
            {
                "_id": "5e390fd03285e463a079968a",
                "customer": "John",
                "total": 9.2,
                "orderDate": "2020-02-04T06:31:44.190Z",
                "__v": 0
            },
            {
                "_id": "5e390fc33285e463a0799689",
                "customer": "Max",
                "total": 10,
                "orderDate": "2020-02-04T06:31:31.311Z",
                "__v": 0
            }
        ]
    }
]

对于您的情况,您需要发送 10 作为 pageSize 值。

【讨论】:

  • 太棒了!我明天会给你一个赏金。
  • @GuerlandoOCs 我很高兴你喜欢我的回答,接受这个作为回答对我来说就足够了,你很友善。
  • 只是一个问题:在聚合管道中,变薄是原子发生的吗?在数据管道的第一步中,它会跳过 x 并限制 y。是否有可能在跳过那些 x 时添加了一个新文档?
  • @GuerlandoOCs 好问题,老实说我不知道​​,但如果我找到答案,我会在这里发表评论。但总的来说,这会很好。
  • 既然我们可以统计文档的总数,那么是否可以使用聚合来创建一个具有自增id的新文档?请看我的问题:stackoverflow.com/questions/60064892/…
猜你喜欢
  • 1970-01-01
  • 2020-06-05
  • 1970-01-01
  • 2010-10-03
  • 1970-01-01
  • 1970-01-01
  • 2010-09-10
  • 2016-12-01
  • 2015-01-18
相关资源
最近更新 更多