Mongoose Typescript - 尽管 X 已在其他文件中声明,但尚未为模型“X”注册架构。
我在 2 个不同的文件中有 2 个名为“用户”和“投资组合”的模式:
//User.model.ts
import mongoose, {Types, Schema} from "mongoose";
export interface IUser {
name: string,
portfolios: Types.ObjectId[],
}
export interface IUserModel extends IUser, Document {}
const userSchema = new Schema<IUserModel>({
name: {
type: String,
required: true,
trim: true
},
portfolios: [{
type: mongoose.Schema.Types.ObjectId,
ref: "Portfolio"
}],
})
export const User = mongoose.model<IUserModel>('User', userSchema)
//Portfolio.model.ts
import mongoose, {Types, Schema} from "mongoose";
export interface IPorfolio{
name: string,
users: Types.ObjectId[],
}
export interface IPorfolioModel extends IPorfolio, Document {}
export const portfolioSchema = new Schema<IPorfolioModel>({
name: {
type: String,
required: true,
trim: true,
unique: true,
},
users: [{
type: Types.ObjectId,
ref: 'User'
}],
})
export const Portfolio = mongoose.model<IPorfolioModel>('Portfolio', portfolioSchema)`
我的 get 函数是一个通用函数,例如
getAll = (model: Model<any>, selectedFields: string, populatedFields: string[]) => (req:Request, res: Response) => {
console.log("Reading all docs...");
model
.find<Array<Document>>()
.select(selectedFields)
.populate(populatedFields || [])
.then((result: object[])=>{
// console.log(result);
let results: object[] = []
result.forEach(ele => {
results.push(snakeToCamel(ele))
})
res.status(httpCode.ok).send({
code: httpCode.ok,
message: "OK",
data: result,
})
})
}
//call function
getUsers = genericFunction.getAll(User,"name portfolios",["portfolios"])
我想收到如下结果:
[
{
"_id": "1",
"name": "System Admin",
"portfolios": [
{
"_id": "2",
"name": "PORTFOLIO",
}
]
}
]
但它抛出错误:
throw new MongooseError.MissingSchemaError(name);
^
MissingSchemaError: Schema hasn't been registered for model "Portfolio".
当我将Portfolio.model.ts中的所有代码复制到User.model.ts中时,它可以工作,但我不知道为什么? 我尝试使用“导入”导入 PortfolioSchema 和 PorfolioModel,但它不起作用。
这与 Typescript 编译器中的树抖动有关。因为您的用户模型实际上是在导入时被引用的,所以模块中的代码将运行以将其注册为猫鼬模式。
getUsers = genericFunction.getAll(User,"name portfolios",["portfolios"])
投资组合反之亦然 - 投资组合不会以任何方式被引用 -> 代码不会运行 -> 不会将“投资组合”注册为猫鼬模式。在 Typescript 中会发生这种情况,因为如果您的代码中有“import Portfolio from '..'”,但没有对 Portfolio 的引用,则 Typescript 编译器将从其输出中删除此导入语句。检查输出文件中的
dist
,并查看其中是否有 Portfolio 模块的 require 或 import 语句(取决于您的 tsconfig)以进行确认。
我自己也遇到过这个问题。假设您不需要在代码中直接引用 Portfolio 来执行任何查询,并且它的存在只是为了填充子文档,您可以通过简单地更改来解决此问题
import Portfolio from './location/file'
到
import './location/file'
动态导入也可以(以及其他一些方式)
const Portfolio = import('./location/file')
但是第一个解决方案可能最适合大多数情况。