【问题标题】:How to validate object keys and values in Mongoose Schema?如何验证 Mongoose Schema 中的对象键和值?
【发布时间】:2017-10-31 06:56:33
【问题描述】:

在我的 Mongoose Schema 中,我试图模拟一个字典 offersInCategory,如下所示:

offersInCategory = { "Electronics": 2, "Furniture": 5 };

Mongoose 不支持字典,所以我不得不在数组中使用对象字面量,如下所示:

offersInCategory: [{
  category: {
    type: String, 
    enum: ['Furniture', 'Household', 'Electronicts', 'Other']
  },
  val: {
    type: Number, 
    min: 0
  }
}]

我对这种方法的问题是感觉不直观。此外,它不会阻止我的模型为同一类别创建多个条目,如下所示:

offersInCategory = [ { category: "Furniture", val: 2 }, { category: "Furniture", val: 0} ]

理想情况下,我的 offerInCategory 属性的结构如下:

offersInCategory : {
  "Furniture" : 0, 
  "Electronics" : 4 
}

但我不知道如何限制它,以便只能将某些键分配给 offersInCategory 对象(有点像键的枚举,而不是值),没有重复。我也不知道如何确保我的受限键的值是特定范围内的数字。这如何实现?

【问题讨论】:

    标签: node.js mongodb mongoose schema


    【解决方案1】:

    选项 1(带有“字典”): 您可以使用 Object 构造函数作为 SchemaType 来使用对象而不是对象数组。这是一个使用SchemaType#validate 适用于您的情况的示例:

    offersInCategory: {
      type: Object,
      validate: object => { //our custom validator, object is the provided object
        let allowedKeys = ['Furniture', 'Household', 'Electronicts', 'Other'];
        let correctKeys = Object.keys(object).every(key => allowedKeys.includes(key)); //make sure all keys are inside `allowedKeys`
    
        let min = 5;
        let max = 10;
        let correctValues = Object.values(object).every(value => value > min && value < max); //make sure all values are in correct range
    
        return correctKeys && correctValues; //return true if keys and values pass validation
      }
    }
    

    这不会应用重复键检查,因为对象不能有重复键,后面出现的键只会覆盖前一个键:

    > let foo = { bar: 4, bar: 5}
    < Object { bar: 5 }
    

    如您所见,前面分配的bar: 4 键被后面的键覆盖。

    选项 2(带数组): 您可以使用SchemaType#validate 在某个文档路径上实现您的自定义验证。这是您想要的示例:

    offersInCategory: [{
      validate: {
        validator: array => { //our custom validator, array is the provided array to be validated
          let filtered = array.filter((obj, index, self) => self.findIndex(el => el.category === obj.category) === index); //this removes any duplicates based on object key
          return array.length === filtered.length; //returns true if the lengths are the same; if the lengths aren't the same that means there was a duplicate key and validation fails
        },
        message: 'Detected duplicate keys in {VALUE}!'
      }
      category: {
        type: String, 
        enum: ['Furniture', 'Household', 'Electronicts', 'Other'] //category must be in this enum
      },
      val: {
        type: Number, 
        min: 0, //minimum allowed number is 0
        max: 10 //maximum allowed number is 10
      }
    }]
    

    如果您对此进行测试,它将删除数组中具有重复键的对象(保留较早的键)并检查数组是否仅包含具有唯一 category 键的对象。

    【讨论】:

    • 太棒了,谢谢!第一个选项正是我正在寻找的那种东西:)
    • @DavidTamrazov 没问题,我很乐意提供帮助!
    • Object 猫鼬上允许的类型? @AndrewLi
    猜你喜欢
    • 2015-09-16
    • 1970-01-01
    • 2021-05-21
    • 1970-01-01
    • 2017-08-05
    • 1970-01-01
    • 2019-12-13
    • 2015-10-24
    • 2016-02-26
    相关资源
    最近更新 更多