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

Express+Mongoose查询MongoDB返回undefined及遍历报错排查

问题根因

三个错误叠加导致了你遇到的所有现象:

  • Mongoose的Model.find()是异步方法,返回Promise/Query对象,原控制器代码没有加await等待查询执行完成,直接把未完成的查询对象传给了EJS模板。最开始模板尝试遍历这个非数组对象时直接触发「无法遍历undefined」的报错;后续调整后遍历到的是Query对象本身的内置属性,这类属性总共有约50个,且都没有name字段,所以渲染出了约50个undefined值。
  • EJS模板里遍历数组的语法写错了:for...in语法用于遍历对象的可枚举键名,遍历数组时拿到的是数组索引(字符串类型的"0"、"1"…)而非数组元素,哪怕查询正常返回了数组,直接访问field.name也会得到undefined。
  • 数据库连接串没有指定目标数据库名,Mongoose默认会连接到Atlas集群的test库,如果你的9条fields数据存在其他业务库下,会出现「客户端工具能查到数据、业务代码查不到」的不一致问题。
修复方案

按顺序修改对应代码即可:

  • 首先修改控制器代码,给查询加await,确保拿到实际的文档数组再传给模板:
const Field = require('../models/field');

module.exports.index = async (req, res) => {
    // 等待查询完成,拿到真实的文档数组
    const fields = await Field.find({});
    res.render('fieldInstances/index', {fields});
};
  • 然后修改EJS模板,把遍历语法改成适合数组遍历的for...of,同时修复复选框id重复的问题(多个DOM元素共用同一个id会导致label关联失效):
<div class="modal-body d-flex">
  <form action="/formInstance/new" method="GET">
    <% // 用for...of遍历数组,直接拿到每个field文档实例 %>
    <% for (let field of fields) { %>
      <% // 用文档_id拼接唯一id,避免多元素id重复 %>
      <input type="checkbox" class="btn-check" id="btn-check-<%= field._id %>" autocomplete="on">
      <label class="btn btn-outline-secondary" for="btn-check-<%= field._id %>" name="fieldInstance[field]"><%= field.name %></label><br>
    <% } %>
    <button type="submit" class="btn btn-success">To the Form!</button>
  </form>
</div>
  • 最后修复数据库连接串,在连接串的/后、?前加上你存储业务数据的实际数据库名,示例如下(把你的业务库名替换成你自己的库名即可):
async function mongooseConnect() {
  await mongoose.connect("mongodb+srv://amillerlite:password@projects.brxq6oa.mongodb.net/你的业务库名?retryWrites=true&w=majority");
};

改完重启服务即可正常渲染出9条字段记录。


内容的提问来源于stack exchange,提问作者amiller_lite

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 21:12:25