设置
假设我们有 Foo
和 Bar
的模式 . Foo
有一个字段 bar
. 此字段可以包含引用文档 Bar
的ObjectId,也可以包含不是ObjectIds的其他任意对象 .
const fooSchema = new mongoose.Schema({
bar: {
type: mongoose.Schema.Types.Mixed,
ref: 'Bar'
}
});
const Foo = <any>mongoose.model<any>('Foo', fooSchema);
const barSchema = new mongoose.Schema({
name: String
});
const Bar = <any>mongoose.model<any>('Bar', barSchema);
问题
现在假设我们有一堆 Foo
文件 .
我希望能够在 bar
字段上使用mongoose的populate来自动将 Bar
文档的引用替换为实际的 Bar
文档本身 . 我还想保留所有其他未引用 Bar
文档的对象 .
通常,我会使用这样的东西来获取所有 Foo
文档,然后填充 bar
字段:
Foo.find().populate('bar')
但是,当遇到 bar
字段中不是ObjectIds的对象时,此方法将抛出异常,而不是保持它们不变 .
UnhandledPromiseRejectionWarning:未处理的承诺拒绝(拒绝ID:1):CastError:强制转换为ObjectId,对于模型“Bar”的路径“_id”处的值“某些任意对象”失败
尝试寻找解决方案
我已经检查过使用 populate
上的 match
选项,要求 Bar
上的字段存在:
Foo.find().populate({
path: 'bar',
match: {
name: {
$exists: true
}
}
}
不幸的是,错误是一样的 .
问题
那么我的问题是,如果字段包含ObjectId,有没有办法让mongoose只有 populate
字段,否则不管它?
1 回答
据我所知,你不能用那种方式填充 . 选择属性在尝试获取填充值后仍然有效,并且在此之前无法对其进行过滤 .
你必须手动完成 . 你可以手动完成 .
优雅地将它包装在模型上的post hook或static方法中 .
另一种选择是发送2个查询:
这当然不是最理想的,因为有2个查询(以及所有人口查询),但这对您来说可能不是问题 . 可读性要好得多 . 当然,您可以更改查找查询以特定地匹配您的案例 .