首页 > 解决方案 > 来自另一个表的 Mongoose 验证值

问题描述

这是我的产品表架构

let schema = new mongoose.Schema({
    title: {type: String, required: true},
    price: {type: Number, required: true},
    description: {type: String, required: true},
    sizes: {type: Object, required: true},
    offer: {type: Number, default: 0},
    images: {type: Array, required: true},
    deal: {type: Boolean, default: false},
    category: {
        _id: {type: Schema.Types.ObjectId, required: true},
        name: {type: String, required: true}
    },
    company_name: {type: String, required: true}
});

我想要做什么

我正在尝试验证category.name我的另一个名为Category.

标签: node.jsmongodbmongoosemongoose-schema

解决方案


可以使用异步验证器并查询类别集合。像这样的东西(使用 promise sytax 作为验证器):

let schema = new mongoose.Schema({
  title: {type: String, required: true},
  price: {type: Number, required: true},
  description: {type: String, required: true},
  sizes: {type: Object, required: true},
  offer: {type: Number, default: 0},
  images: {type: Array, required: true},
  deal: {type: Boolean, default: false},
  category: {
      _id: {type: Schema.Types.ObjectId, required: true},
      name: {
        type: String, 
        required: true,

        validate: function(nameVal) {
          return new Promise(function(resolve, reject) {
            let Category = mongoose.model('Category');  //you would have to be sure that Category model is loaded before this one.  One reason not to do this        
            Category.findOne({name: nameVal}, (err, cat) => resolve(cat ? true : false));  //any non null value means the category was in the categories collection
          });
        }

      }
  },
  company_name: {type: String, required: true}
});

对此的一些想法:

  1. 这记录在http://mongoosejs.com/docs/validation.html#async-custom-validators
  2. 正如它在那里所说,默认情况下验证器不会在更新时运行。那里有很多警告需要阅读。
  3. 根据我使用 NoSQL DB 的经验,创建新产品的代码会注意确保分配的类别有效。该代码可能在之前的某个时间从数据库中找到了该类别。因此,进行验证器查找将是多余的。但是您可能会遇到这样一种情况,即您有很多创建产品的代码并希望在一个地方进行验证。
  4. 当我看到您将 {_id: ..., name: ...} 的文档存储为 Product 架构中的类别字段时,我认为您可能想要这个:

    ...
    category: {Schema.Types.ObjectId, ref: 'Category'},
    

    这允许您存储对从类别集合中检索到的类别的引用。 如果您在查询中使用填充方法,Mongoose 会在您检索产品时为您内联加载类别文档。请参阅http://mongoosejs.com/docs/populate.html。填充功能有很多选项,您可能会发现它们很有用。据我所知,它不会验证类别在保存时是否有效。但是,如果您采用这种方法,您可能已经在保存之前在代码中查找过该类别(请参阅链接以更好地了解我的意思)。从本质上讲,这使您可以使用 MongoDB 进行类似的行为,从而节省存储空间以及人们期望从“规范化”中获得的其他好处。


推荐阅读