如何在JavaScript对象中以数据库返回分类为键、对应文章数组为值
问题根因
你的问题本质是JavaScript异步执行顺序问题:Mongoose的所有查询都是异步操作,你调用res.json返回接口响应的时候,分类关联文章的查询、最新/热门文章的查询都还没执行完,所以返回的都是初始空值。除此之外你还存在嵌套查询逻辑冗余、数组嵌套错误的问题。
修复方案
直接用async/await + Mongoose内置的populate关联查询重写路由,逻辑更清晰,性能更高,避免回调地狱:
// 把路由回调改成async函数支持await app.get('/', async function(req, res) { try { // 并行查询所有需要的基础数据,提升接口响应速度 const [latest, trend, allArticles, categoryList] = await Promise.all([ // 最新文章,直接拿结果不需要手动push Article.find().limit(7).sort({$natural: -1}), // 热门文章 Article.find().limit(5).sort({hits: -1}), // 全量文章 Article.find(), // 所有分类 + 直接populate关联的文章,不需要自己循环查 Category.find({}, {projection: {category:0}}).populate('articles') ]) // 构造categoryObj const categoryObj = {} categoryList.forEach(category => { // 直接用populate返回的关联文章数组即可 categoryObj[category.name] = category.articles }) // 统一返回结果 res.json({ allArticles, latest, trend, categoryObj }) } catch (err) { // 统一处理所有查询错误 console.error(err) res.status(500).json({error: '服务器内部错误'}) } })
原代码的问题说明
- 执行顺序错误:你触发返回的
Article.find回调优先级高于分类查询、分类下文章查询的回调,返回数据时异步查询还没完成,拿到的都是空初始值 - 逻辑冗余:Mongoose自带
populate关联查询能力,不需要手动循环调用Article.findById查每个分类下的文章,性能差还容易出现作用域问题 - 数组嵌套错误:你每次查询到单篇文章都把整个临时数组
newarrpush到分类数组里,导致最终每个分类下的结构是多层嵌套的数组,不是预期的平级文章数组 - 错误处理缺失:原代码没有统一的错误捕获逻辑,任意查询报错都会导致接口无响应
内容的提问来源于stack exchange,提问作者Asif Habib
相关产品推荐
相关产品推荐

