Node+Express+Mongo+Pug MVC应用:如何聚合多模块数据到首页?
问题描述
我有一个基于Node+Express+Mongo+Pug的MVC应用,目前已实现stories、questions、reviews等独立模块(每个模块包含Controller+Model+View,可完成MongoDB数据写入与视图展示)。现在需要创建新控制器,将这些模块的数据聚合后在首页按行展示,对该控制器的实现方式存在困惑。
以下是单个Story模块的示例代码:
Story模块示例
控制器代码
const Story = require('../models/Story'); exports.getStories = (req, res, next) => { Story.find() .then((stories) => { res.render('story', {title:'StoryTata', stories}); }) .catch(() => { res.send('Sorry!'); }); };
视图代码(Pug)
extends layout block content body h1 #{title} if stories table tr th Title th Body th userName each story in stories tr td= story.title td= story.body td= story.userName else p No registrations yet :( a(href='/story/add') Add New Story
模型代码
// storyModel let mongoose = require('mongoose'); // Add Story let storySchema = mongoose.Schema({ title:{ type:String, required: true }, body:{ type:String, required: true }, userName:{ type: String, required: true } }, { timestamps: true }); let Story = module.exports = mongoose.model('Story', storySchema);
解决方案
1. 创建首页控制器
核心思路是并行查询多个模块的数据,通过Promise.all同时发起MongoDB查询,待所有数据返回后统一传递给首页视图。
控制器代码(controllers/home.js)
const Story = require('../models/Story'); const Question = require('../models/Question'); const Review = require('../models/Review'); // 首页数据聚合控制器 exports.getHome = (req, res, next) => { // 并行执行三个模块的数据查询 Promise.all([ // 可选:按创建时间倒序,取最新5条数据(避免首页加载过多内容) Story.find().sort({ createdAt: -1 }).limit(5), Question.find().sort({ createdAt: -1 }).limit(5), Review.find().sort({ createdAt: -1 }).limit(5) ]) .then(([stories, questions, reviews]) => { // 将所有模块数据传递给首页视图 res.render('home', { title: '首页', stories, questions, reviews }); }) .catch(err => { console.error('首页数据加载失败:', err); res.send('加载数据失败,请稍后重试'); }); };
2. 编写首页Pug视图
在视图中按模块拆分展示数据,每个模块对应一个区块,按行展示内容:
视图代码(views/home.pug)
extends layout block content h1 首页 // 故事模块展示区 section h2 最新故事 if stories.length table tr th 标题 th 内容预览 th 作者 each story in stories tr td= story.title td= story.body.substring(0, 60) + '...' // 截断长内容,优化展示 td= story.userName else p 暂无故事内容 // 问题模块展示区 section h2 最新问题 if questions.length table tr th 标题 th 内容预览 th 提问者 each question in questions tr td= question.title td= question.content.substring(0, 60) + '...' td= question.userName else p 暂无问题内容 // 评价模块展示区 section h2 最新评价 if reviews.length table tr th 标题 th 评价预览 th 评价者 each review in reviews tr td= review.title td= review.content.substring(0, 60) + '...' td= review.userName else p 暂无评价内容
3. 配置首页路由
在路由文件(如routes/index.js或app.js)中添加首页路由:
const homeController = require('../controllers/home'); // 首页路由 app.get('/', homeController.getHome);
关键说明
- 并行查询优化:使用
Promise.all替代嵌套回调,同时发起多个MongoDB查询,大幅提升数据加载效率。 - 数据筛选:通过
sort({ createdAt: -1 })按创建时间倒序,limit(5)限制返回数量,避免首页加载过多数据影响性能。 - 错误处理:统一捕获所有查询的错误,打印日志并返回友好提示,便于排查问题。
内容的提问来源于stack exchange,提问作者aksit
相关产品推荐
相关产品推荐

