首页 文章

处理猫鼬人口例外情况

提问于
浏览
0

我们有一些Mongoose(5.x)模型,并使用ref和填充来获取一些孩子 . 当填充失败时,我无法处理异常 .

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);

运行此查询会导致一些预期的错误和一些意外错误 . 这些错误会阻止 endpoints 返回任何数据 .

获取帖子时出错CastError:对于模型“Domain”[2](节点:5740),路径“_id”处的值“www.google.com”导致ObjectId失败UnhandledPromiseRejectionWarning:未处理的承诺拒绝(拒绝ID:1):CastError :对于模型“域”,路径为“_id”的值“www.google.com”的转换为ObjectId失败

为什么我收到UnhandledPromseRejectionWarning,是不是处理拒绝的.catch()?

遇到错误时,我想要两种可能的结果之一:

  • 将该文档的域设置为null

  • 如果无法做到这一点,请从结果集中排除该文档并继续

这两种选择都可能吗?

2 回答

  • 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;
    }
    
  • 1

    您可以尝试使用$type运算符:

    const posts = model.find({ domain: { $type: 'objectId' } }).limit(20).populate('user').populate('domain');
    

    这样,您可以从结果中排除所有带有“字符串”域的文档 .

    顺便说一句,最好的解决方案是使数据同质化,也许使用一个循环,为所有字符串域找到正确的域文档,并使用其_id作为ref .

相关问题