[英]Is it possible to have mongoose populate a Mixed field only if the field contains an ObjectId?
假设我们有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
字段上使用猫鼬的populate
来自动将Bar
文档的引用替换为实际的Bar
文档本身。 我还希望保留所有未引用Bar
文档的其他对象。
通常,我会使用类似的方法来获取所有Foo
文档,然后填充bar
栏:
Foo.find().populate('bar')
但是,此方法在bar
字段中遇到非ObjectId的对象时会抛出异常,而不是使其保持不变。
UnhandledPromiseRejectionWarning:未处理的承诺拒绝(拒绝ID:1):CastError:模型“ Bar”的路径“ _id”上的值“某些任意对象”的CastId失败
我已经检查过在populate
上使用match
选项,要求在Bar
存在一个字段:
Foo.find().populate({
path: 'bar',
match: {
name: {
$exists: true
}
}
}
不幸的是,错误是相同的。
所以我的问题是,有什么方法可以让猫鼬只populate
一个字段包含ObjectId的情况下populate
该字段,否则将其保留?
据我所知,您不能使用填充方式。 选择属性在尝试获取人口值之后才起作用,并且在此之前无法对其进行过滤。
您将必须手动执行。 您可以手动执行。
let foos = await Foo.find({});
foos = foos.map(function (f) {
return new Promise(function (resolve) {
if (condition()) {
Foo.populate(f, {path: 'bar'}).then(function(populatedF){
resolve(f);
});
} else {
resolve(f);
}
});
});
await Promise.all(foos).then(function (fs) {
res.status(200).json(fs);
});
优雅地将其包装在模型的post hook或static方法中。
另一种选择是发送2个查询:
const foosPopulated = Foo.find({ alma: { $type: 2 } }).populate('bar'); // type of string
const foosNotPopulated = Foo.find({ alma: { $type: 3 } }); // type of object
const foos = foosPopulated.concat(foosNotPopulated);
当然这是次优的,因为有2个查询(以及所有人口查询),但这也许对您来说不是问题。 可读性好得多。 当然,您可以更改查找查询以专门匹配您的案例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.