通过名称查找Mongoose Model 解决Schema未注册报错问题
Mongoose动态Model查询报错解决方案
报错根因
Schema hasn't been registered for model "xxx"报错的核心是:你调用mongoose.model(modelname)获取模型时,该名称的模型未在当前mongoose连接实例上完成注册。即使数据库中存在对应集合,mongoose也不会自动将数据库集合注册为可用模型,必须手动注册后才能调用接口访问。
如果你的代码拆分在不同路由模块中,也可能出现注册模型的代码未被提前执行、导致其他路由访问时模型未注册的问题。
适配动态Model名的解决方案
由于你无法提前预知Model名称,可通过存在判断+动态注册的逻辑处理,两种实现方式可选:
方案1:自行维护模型缓存(性能更高)
提前抽离公共Schema,封装统一的动态模型获取工具函数,已注册过的模型直接从缓存读取:
// 公共Schema定义 const commonSchema = new Mongoose.Schema({ var1: String, var2: String, var3: String }, { timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' } }); // 已注册模型缓存 const modelCache = new Map(); // 动态模型获取工具函数 function getDynamicModel(modelName) { if (modelCache.has(modelName)) { return modelCache.get(modelName); } // 未注册则当场注册,第三个参数可选:如果你的数据库集合名和model名完全一致、不需要自动转小写复数,就加上第三个参数 const model = mongoose.model(modelName, commonSchema, modelName); modelCache.set(modelName, model); return model; }
后续所有场景都通过该工具函数获取模型即可:
// 存储数据场景 const model = getDynamicModel(modelname); const doc = new model({var1, var2, var3}); doc.save().then((resp) => { return res.status(200).json(resp); }) // 其他路由查询场景 const model = getDynamicModel(modelname); // 后续正常调用find/update等API即可
方案2:基于Mongoose自带API判断
不需要自行维护缓存,直接调用mongoose.modelNames()获取已注册模型列表判断:
function getDynamicModel(modelName) { if (mongoose.modelNames().includes(modelName)) { return mongoose.model(modelName); } return mongoose.model(modelName, commonSchema, modelName); }
注意事项
如果你的数据库集合名是自定义的,不是Mongoose默认生成的「model名小写复数」格式,注册模型时必须传入第三个参数指定实际集合名,否则即使模型注册成功也无法匹配到数据库中的对应数据。
内容的提问来源于stack exchange,提问作者Blob Army
相关产品推荐
相关产品推荐

