MongoDB查询EJS渲染报错:operators.forEach不是函数的解决方法
解决MongoDB集合数据在EJS表格中展示时的
operators.forEach is not a function错误 问题背景
在MongoDB中拥有operator集合,想要在EJS表格中展示该集合的所有信息,但运行时出现错误:operators.forEach is not a function。相关代码如下:
集合模型
const operatorSchema = new Schema({ "operatorName": { type: String }, "productsSerialNumber":[{"productSerialNumbers": String}], "operatorSerialNumber": { type: Number }, "users":[{ "email":String, "payment":Number, "paymentsData": Date, }], "operatorState":{ type: Boolean, } });
原查询函数
exports.getOperatorInformations = (req, res, next)=>{ Operators.find({},function(err,docs){ docs.forEach(function(dataCatch){ console.log(dataCatch.users) res.render('home',{"operators": dataCatch}); }) }) } }
原EJS代码片段
<% operators.forEach(function(data){ %> <tr> <td> <%= data.operatorName %> </td> <td> <%= data.productsSerialNumber %> </td> <td> <%= data.productsSerialNumber %> </td> <% })%> <% data.users.forEach(function(data){ %> <td> <%= data.users.email %> </td> <td> <%= data.users.paymentsData %> </td> <td> <!-- <%= data.users.payment %> --> </td> </tr> <% })%> </tr>
错误原因
- 后端数据传递错误:原查询函数中,遍历
docs(查询返回的文档数组)时,每次将单个文档dataCatch赋值给operators传给EJS模板。这导致EJS中的operators是单个对象而非数组,自然没有forEach方法。 - EJS逻辑错误:变量名重复使用(两次循环都用
data)导致逻辑混乱;嵌套循环结构错误,用户循环放在运营商循环外部,无法正确关联数据;访问用户属性时路径错误(data.users.email应为当前循环的用户对象属性)。
修复步骤
1. 修复后端查询函数
去掉对docs的遍历,直接将整个文档数组传给模板,同时添加错误处理:
exports.getOperatorInformations = (req, res, next) => { Operators.find({}, (err, docs) => { if (err) { console.error(err); return next(err); // 传递错误给错误处理中间件 } // 将整个文档数组作为operators传给EJS模板 res.render('home', { operators: docs }); }); };
2. 修复EJS表格代码
修正循环结构、变量名和属性访问方式,同时处理数组类型的字段:
<table> <thead> <tr> <th>运营商名称</th> <th>产品序列号</th> <th>用户邮箱</th> <th>支付日期</th> </tr> </thead> <tbody> <% operators.forEach(function(operator) { %> <!-- 遍历每个运营商的用户列表 --> <% operator.users.forEach(function(user) { %> <tr> <td><%= operator.operatorName %></td> <td> <!-- 遍历产品序列号数组并拼接显示 --> <% operator.productsSerialNumber.forEach(function(product, idx) { %> <%= product.productSerialNumbers %><% if (idx !== operator.productsSerialNumber.length - 1) { %>, <% } %> <% }) %> </td> <td><%= user.email %></td> <td><%= user.paymentsData.toLocaleString() %></td> <!-- 格式化日期显示 --> </tr> <% }) %> <!-- 处理无用户的运营商 --> <% if (operator.users.length === 0) { %> <tr> <td><%= operator.operatorName %></td> <td> <% operator.productsSerialNumber.forEach(function(product, idx) { %> <%= product.productSerialNumbers %><% if (idx !== operator.productsSerialNumber.length - 1) { %>, <% } %> <% }) %> </td> <td>无用户</td> <td>-</td> </tr> <% } %> <% }) %> </tbody> </table>
修复说明
- 后端:确保传递给EJS的
operators是数组类型,这样就能正常调用forEach方法。 - EJS:
- 用不同变量名区分运营商(
operator)和用户(user),避免变量冲突。 - 将用户嵌套在运营商循环内部,保证数据关联正确。
- 遍历
productsSerialNumber数组,将多个序列号拼接显示,避免直接输出数组对象。 - 格式化日期显示(
toLocaleString()),提升可读性。 - 添加无用户时的占位显示,保证表格结构完整。
- 用不同变量名区分运营商(
内容的提问来源于stack exchange,提问作者hobik
相关产品推荐
相关产品推荐

