You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mongoose排序返回随机结果:按sorter字段降序排序失效

问题:MongoDB查询结果无法按sorter字段降序排序,返回结果顺序随机

我有一个名为payments的集合,其中包含sorter字段,希望将查询结果按sorter字段降序排序,但当前代码每次返回随机结果,相关代码如下:

return ApiProtectedRoute(
  req,
  res,
  (protectedUserid, protectedUsername, protectedEmail, protectedBalance) => {
    paymentModels
      .find({
        userId: protectedUserid
      }, function(err, payments) {
        if (payments.length == 0) {
          res.status(400).json({
            error: true,
            message: "No payments found",
            info: "getPayments",
          });
        } else if (payments.length > 0) {
          let paymentsWithUsername = [];
          payments.forEach((payment) => {
            userModels.findOne({
              _id: payment.userId
            }, function(err, user) {
              if (err) console.log(err);
              paymentsWithUsername.push({
                ...payment._doc,
                username: user.username,
                email: user.email,
              });
              if (paymentsWithUsername.length === payments.length) {
                res.status(200).json({
                  error: false,
                  payments: paymentsWithUsername,
                  info: "getPayments",
                });
              }
            });
          });
        } else {
          res.status(400).json({
            error: true,
            message: "Something went wrong",
            info: "getPayments",
          });
        }
      })
      .sort({
        sorter: -1
      });
  }
);

Payments集合截图:
payments集合


解决方案

问题根源

  1. 排序逻辑未生效:Mongoose中如果给find()直接传入回调函数,查询会立即执行,后续链式调用的.sort()不会被应用,等于没加排序规则。
  2. 异步操作打乱顺序:forEach里的userModels.findOne()是异步操作,每个查询完成时间不确定,导致paymentsWithUsername数组的元素顺序随机,即使数据库返回了排序好的结果,最终返回的数组还是乱的。

修正后的代码(用async/await简化逻辑,保证排序和顺序)

return ApiProtectedRoute(
  req,
  res,
  async (protectedUserid, protectedUsername, protectedEmail, protectedBalance) => {
    try {
      // 先执行带排序的查询,用await获取数据库返回的排序结果
      const payments = await paymentModels
        .find({ userId: protectedUserid })
        .sort({ sorter: -1 });

      if (payments.length === 0) {
        return res.status(400).json({
          error: true,
          message: "No payments found",
          info: "getPayments",
        });
      }

      // 用Promise.all并行查询用户信息,同时保证结果顺序和原payments一致
      const paymentsWithUsername = await Promise.all(
        payments.map(async (payment) => {
          const user = await userModels.findOne({ _id: payment.userId });
          return {
            ...payment._doc,
            username: user?.username,
            email: user?.email,
          };
        })
      );

      res.status(200).json({
        error: false,
        payments: paymentsWithUsername,
        info: "getPayments",
      });
    } catch (err) {
      console.error(err);
      res.status(400).json({
        error: true,
        message: "Something went wrong",
        info: "getPayments",
      });
    }
  }
);

关键修改点

  • 移除find()的回调,改用await配合.sort()链式调用,确保排序规则在数据库层面生效,直接拿到排序好的结果。
  • 用map+Promise.all替代forEach异步回调,既保证查询效率,又让最终数组顺序和原排序结果完全一致。
  • 增加try/catch统一处理异常,避免遗漏错误场景。

内容的提问来源于stack exchange,提问作者Anurag

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 01:30:55