Axios GET 进入 for 循环导致 "Sort exceeded memory limit" 错误

Axios GET in for loop causing "Sort exceeded memory limit" error

我正在尝试从我的 mongoDB 数据库中一次加载一个条目。它适用于大约 400/1000 个条目,然后因以下错误而中断:

Executor error during find command :: caused by :: Sort exceeded memory limit of 33554432 bytes, but did not opt in to external sorting. Aborting operation. Pass allowDiskUse:true to opt in.

我的 Axios 获取请求如下所示:

    for (let i = 0; i < total; i++) {
      await axios({
        method: "GET",
        url: "/api/entries/",
        params: { from: index + i, _limit: 1 },

      })
        .then((res) => {
          setPics((prev) => {
            return [...new Set([...prev, ...res.data])];
          });
          setIndex((prev) => prev++)
          setMoreEntries(res.data.length > 0)
        })

    }

在我的控制器中,我的 GET 函数如下所示:

const getEntries = asyncHandler(async (req, res) => {
  const entries = await Entry.find().allowDiskUse(true).sort({ createdAt: 'desc' }).skip(req.query.from).limit(req.query._limit)
  res.status(200).json(entries)
})

一切正常,直到加载了大约一半的条目,然后它中断了。我以为添加 allowDiskUse(true) 会解决它,但结果相同。

编辑:我应该提一下,如果我取出 .sort({ createdAt: 'desc' }) 它会完美运行,但加载顺序相反。

语法本身很好,我不太清楚为什么它不适合你。

我有两个可能的理论:

  1. 您正在 Atlas 上托管您的数据库,并且正在为他们的 docs:
  2. 中指定的此操作使用不合格的实例

Atlas M0 free clusters and M2/M5 shared clusters don't support the allowDiskUse

  1. 看来您使用的是 mongoose,也许您使用的是旧版本,此游标标志有问题或语法不同。

无论问题的根源如何,我都建议您通过以下任一方式解决此问题:

  1. createdAt上创建索引,存在索引时排序不会将文档扫描到内存中,这将提高查询效率并解决此问题。

  2. 只需使用 _id 索引并使用 { _id: -1} 排序,从您关于删除排序操作并以相反顺序获取文档的评论看来,您的 createdAt 对应文档创建日期(有意义),ObjectId _id 单调递增,这意味着您可以只使用该字段进行排序。

我最后只是做了一个倒退 for-loop,并使用跳过而不是排序,比如

const getOne = asyncHandler(async (req, res) => {
  const entry = await Entry.findOne({}, {}).allowDiskUse(true).skip(req.query.from)

  res.status(200).json(entry)
})

这对我来说非常有效,但汤姆的回答正是我想要的,谢谢 :)