在我的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} ]
理想情况下,我的offersInCategory属性的结构如下:
offersInCategory : {
"Furniture" : 0,
"Electronics" : 4
}
但我不知道如何限制它,以便只能将某些键分配给offersInCategory
对象(有点像键的枚举,而不是值),没有重复。我也不知道如何确保限制键的值是特定范围内的数字。如何实现这一目标?
答案 0 :(得分:2)
选项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
键的对象。