如何在ExpressJS(Mongoose)中对MongoDB查询结果按指定字段排序分组
解决ExpressJS中Mongoose聚合查询分组排序并返回文档详情的问题
你的问题在于当前的聚合操作只做了分组(仅保留了分组ID),没有保留文档的实际内容,也没有处理层级排序的逻辑。我们可以通过调整聚合管道,先排序再分组并保留所需字段,最后在代码里格式化出你想要的结构。
正确的聚合查询代码
const spellings = await Spelling.aggregate([ // 第一步:先按keyStageLevel升序,再按spellingLevel升序排序 { $sort: { keyStageLevel: 1, spellingLevel: 1 } }, // 第二步:按keyStageLevel分组,收集每个分组内的文档核心字段 { $group: { _id: "$keyStageLevel", spellingGroups: { $push: { spellingLevel: "$spellingLevel", name: "$name", spellings: "$spellings" } } } }, // 可选:确保每个keyStage下的spellingGroups严格按spellingLevel排序 { $addFields: { spellingGroups: { $sortArray: { input: "$spellingGroups", sortBy: { spellingLevel: 1 } } } } }, // 最后按keyStageLevel升序排列分组结果 { $sort: { _id: 1 } } ]);
代码解释
- $sort 阶段:先对所有文档按
keyStageLevel升序排序,同一keyStageLevel下再按spellingLevel升序排序,确保后续分组时的顺序符合预期。 - $group 阶段:以
keyStageLevel作为分组ID,用$push将每个文档的spellingLevel、name、spellings字段存入spellingGroups数组,这样每个分组就包含了该keyStage下的所有相关文档信息。 - $sortArray(可选):如果担心前面的排序在分组后顺序被打乱,可以用
$sortArray再次对每个分组内的spellingGroups数组按spellingLevel排序,保证顺序准确。 - 最终$sort:对分组后的结果按
keyStageLevel(即_id)升序排列,确保输出的keyStage顺序正确。
将结果格式化为你想要的输出
拿到聚合结果后,你可以遍历结果生成预期的文本格式:
// 格式化输出 const formattedOutput = spellings.map(group => { let output = `keyStageLevel ${group._id}\n`; group.spellingGroups.forEach(item => { output += `spellingLevel ${item.spellingLevel}\n`; output += `name: "${item.name}", spellings: [ "${item.spellings.join('", "')}" ]\n`; }); return output; }).join('\n'); console.log(formattedOutput);
这样输出的结果就会和你预期的格式一致:
keyStageLevel 2 spellingLevel 3 name: "second", spellings: [ "her", "is", "another" ] spellingLevel 4 name: "third", spellings: [ "snother", "list" ] keyStageLevel 4 spellingLevel 2 name: "first", spellings: [ "here", "is", "you" ]
内容的提问来源于stack exchange,提问作者Stuart Brown
相关产品推荐
相关产品推荐

