Fla*_*nix 3 javascript mongoose mongodb node.js
假设我正在做一个关于你可以购买的水果的模式。在这个模式中,水果有一个价格范围:
let fruit = {
name: "banana",
price: {
currency: "EUR",
range: [2, 10]
}
};
Run Code Online (Sandbox Code Playgroud)
为了实现保存上述对象,我尝试使用以下架构:
let fruitSchema = {
name: {type: String, required: true},
price: {
currency: {type: String, required: true},
range: [{
type: Number,
min: 0
}],
validate: [arraySize]
}
};
const arraySize = function arrayLimit(val) {
return val.length === 2;
};
Run Code Online (Sandbox Code Playgroud)
我对范围部分的解决方案感觉笨拙,过于复杂,并且不检查最大范围值是否大于最小范围值,即不检查是否 10 > 2。
I decided to have both values in my Schema separately, like in the example bellow:
income: {
currency: { type: String },
range: {
min: { type: Number, min: 0 },
max: { type: Number, min: 0 }
}
}
Run Code Online (Sandbox Code Playgroud)
However, now I am left with a problem. How to check that my MAX >= MIN at all times, and that MIN <= MAX ??
Given that nor MIN nor MAX are mandatory, one can have an object with just an upper range, or just a lower one.
To fix this validation issue, I used custom validator functions. Validators were the missing piece in the puzzle, and allowed me to enforce max and min restrictions:
validate object for min:
validate: {
validator: function(val){
const currMax = this.target.income.range.max;
return (currMax !== undefined ? val <= currMax : true);
},
message: "The MIN range with value {VALUE} must be <= than the max range!"
}
Run Code Online (Sandbox Code Playgroud)
validate object for max:
validate: {
validator: function(val) {
const currMin = this.target.income.range.min;
return (currMin !== undefined ? val >= currMin : true);
},
message: "The MAX range with value {VALUE} must be >= than the min range!"
}
Run Code Online (Sandbox Code Playgroud)
Thus, the final result is as follows:
income: {
currency: { type: String },
range: {
min: {
type: Number, min: 0,
validate: {
validator: function(val){
const currMax = this.target.income.range.max;
return (currMax !== undefined ? val <= currMax : true);
},
message: "The MIN range with value {VALUE} must be <= than the max range!"
}
},
max: {
type: Number, min: 0,
validate: {
validator: function(val) {
const currMin = this.target.income.range.min;
return (currMin !== undefined ? val >= currMin : true);
},
message: "The MAX range with value {VALUE} must be >= than the min range!"
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
This solution is nice, shows advanced knowledge and does the requirements. In you try to insert an object where MIN > MAX, you will have a nice error message with the VALUE being inserted.
However, I have the following questions / suggestions for improvement, that I didn't add because I don't yet know how to do:
The validator will keep inconsistent objects from being inserted. However, when it does not prevent bad UPDATES, i.e., the following example will work on an object with MIN = 10:
ObjModel.update(
{ _id: "58dd26b5476664e33eec4b93" },
{ $set: {"income.range.max": 1}} );
To do updates on objects using validators, you must use the save method, and follow the convention described at the end of the mongoose docs.
Model.findOne({ name: 'borne' }, function (err, doc){
doc.name = 'jason borne';
doc.visits.$inc();
doc.save();
});
Run Code Online (Sandbox Code Playgroud)
Which will trigger the validator as expected.
{VALUE}. However, can you use other values of the object? When comparing MIN and MAX, it would be useful to print the value being evaluated as well as the values it is being compared to. Hope it helps, and inspires!
| 归档时间: |
|
| 查看次数: |
3377 次 |
| 最近记录: |