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集合截图:
解决方案
问题根源
- 排序逻辑未生效:Mongoose中如果给
find()直接传入回调函数,查询会立即执行,后续链式调用的.sort()不会被应用,等于没加排序规则。 - 异步操作打乱顺序:
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
相关产品推荐
相关产品推荐

