我们有一些Mongoose(5.x)模型,并使用ref和populate来获取一些孩子。当填充失败时,我无法处理异常。
const postSchema = new mongoose.Schema({
title: {
type: String,
},
url : {
type: String,
},
domain:{
type: mongoose.Schema.Types.ObjectId,
ref: 'Domain'
},
user:{
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}
});
postSchema模型的domain属性最初是String类型,最近已升级为ObjectID Ref。现有数据现在是混合的 - 大多数帖子都有一个字符串作为域名,而少数帖子有一个ObjectId。删除这些数据并重新开始会很简单,但我决定让代码优雅地处理这个并以正确的方式处理它。
我们有一个(简化的)查询:
const posts = model.find().limit(20).populate('user').populate('domain');
posts.catch(err => console.log('Error getting posts ' + err);
运行此查询会引发一些预期错误和一些意外错误。这些错误会阻止端点返回任何数据。
获取帖子时出错CastError:Cast为ObjectId的值失败 " www.google.com"在路径" _id" for model" Domain" [2] (节点:5740)
UnhandledPromiseRejectionWarning:未处理的承诺拒绝 (rejection id:1):CastError:对于值,转换为ObjectId失败 " www.google.com"在路径" _id" for model" Domain"
为什么我收到UnhandledPromseRejectionWarning,是不是处理拒绝的.catch()?
当遇到错误时,我想要两种可能的结果之一:
这些选项中的任何一个都可以吗?
答案 0 :(得分:1)
您可以尝试使用$type运算符:
const posts = model.find({ domain: { $type: 'objectId' } }).limit(20).populate('user').populate('domain');
通过这种方式,您可以使用'字符串'从结果中排除所有文档。域。
顺便说一句,最好的解决方案是使数据同质化,也许使用一个循环,为所有字符串域找到正确的域文档,并使用其_id作为参考。
答案 1 :(得分:1)
您可以尝试使用custom schema types
const mongoose = require('mongoose');
const {ObjectId} = mongoose.Schema.Types;
if (!('DomainId' in mongoose.Schema.Types)) {
class DomainId extends mongoose.SchemaType {
constructor (value, options) {
value = (value instanceof ObjectId) ? value : new ObjectId(value);
super(value, options, 'DomainId');
}
cast (val) {
const _val = (value instanceof ObjectId) ? value : new ObjectId(value);
return _val;
}
}
mongoose.SchemaTypes.DomainId = DomainId;
}