更新数组中的整个对象并验证必填字段

时间:2019-09-22 14:19:51

标签: node.js mongodb mongoose

运行猫鼬4.13.19我遇到了一个问题,试图验证数组中对象的必填字段。

模式:

const PartSchema = new Schema({
  partNumber: { type: Number, required: true },
  name: { type: String, required: true }
},{
  _id: false
});

const CarSchema = new Schema({
  make: { type: String, required: true },
  model: { type: String, required: false },
  parts: [PartSchema]
});

const DealershipSchema = new Schema({
  name: { type: String, required: true },
  cars: [CarSchema]
});

var Dealership = mongoose.model('Dealership', DealershipSchema);

查找并更新整个汽车对象

const carId = 10;
const update = {
    $set: {
      'cars.$': car
    }
  };

  Dealership.findOneAndUpdate({'cars._id': carId}, update, {new: true, runValidators: true}, function(err, dealership) {
    // update complete
  });

如果我要更新的汽车的零件缺少name属性,则查询仍将成功运行,并验证零件对象上的name字段。 IE:

const car = {
   parts: [{
     partNumber: 37
   }]
}

仔细查看猫鼬文档和一些问题,由于当前数据库对象不在内存中,猫鼬无法确定是否存在猫鼬将无法在findOneAndUpdate上针对缺少的字段运行所需的验证的问题零件的标题已经在数据库中设置,不会受到查询的影响。

在这种情况下,我正在更新整个汽车对象,它将覆盖数据库中该汽车存在的所有内容。猫鼬不会验证这一点很奇怪,我想是一个解决方法的时间...

选项1

在运行查询之前,请确保已填充所有字段,对于缺少的字段,请为它们添加未定义的值。

const car = {
   parts: [{
     partNumber: 37,
     name: undefined
   }]
}

在这种情况下,猫鼬会看到我正在尝试将所需的属性设置为undefined。这将正确地使所需的名称验证失败。似乎有点脏,因为我的模型并没有在猫鼬级别真正保护自己,因为我依赖于后查询逻辑来清理和清理查询。

选项#2

为汽车模式编写我自己的验证器,以验证所有属性。

function hasRequiredNameProperty(parts) {
  // loop parts array and ensure that each part has its name property
  // set.  If not fail validation here.
}

CarSchema.path('parts').validate(hasRequiredNameProperty, 'Car has at least part object that is missing its "name" property which is required');

这似乎比选项1更好,因为现在至少在猫鼬级别进行了验证。但是,仍然很棘手,因为我已经按照模式中的要求设置了名称字段。现在,我必须编写更多逻辑以确保设置了name属性。这意味着对于所有必填字段,都必须实现相同的逻辑。

选项3

放弃使用 findOneAndUpdate 。这似乎是mongo / mongoose的大问题。由于使用findOneAndUpdate内存中没有当前数据库文档,因此无法始终验证必填字段。

因此,在这种情况下,只需先找到文档以将其拉入内存即可:

  Dealership.findOne({'cars._id': carId}, function(err, dealership) {
    // find the car w/ carId
    // Then update the entire car object
    // save the dealership
    dealership.save();
  }

好,所以只需要在一个地方设置必填项即可,这在架构中很棒。但是现在我避免了mongo最好的事情之一,它的原子更新。现在,我必须先进行查询,然后执行更新。

我认为这些解决方案都不是特别干净的。好像猫鼬可以验证汽车对象及其零件,因为我在findOneAndUpdate中设置了整个对象。我想念什么吗?还有另一种方法吗?

0 个答案:

没有答案