You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>

错误原因

  1. 后端数据传递错误:原查询函数中,遍历docs(查询返回的文档数组)时,每次将单个文档dataCatch赋值给operators传给EJS模板。这导致EJS中的operators是单个对象而非数组,自然没有forEach方法。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 17:54:33