如何在mongoose模式中表示范围?

时间:2022-02-24 16:56:47

Background

Lets say I am doing a schema about fruits that you can buy. In this schema, a fruit has a price range:

让我们说我正在做一个关于你可以买的水果的架构。在此架构中,水果的价格范围为:

let fruit = {
    name: "banana",
    price: {
        currency: "EUR",
        range: [2, 10]
    }
};

To achieve saving the above object, I am trying to use the following schema:

为了实现保存上面的对象,我试图使用以下模式:

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;
};

Problem:

My solution to the range part feels clunky, over complicated and doesn't check if the Max range value is bigger than the Min range value, i.e., doesn't check if 10 > 2.

我对范围部分的解决方案感觉笨重,过于复杂,并且不检查Max范围值是否大于Min范围值,即,不检查10> 2。

Question:

  • How would you implement a price range in a schema in mongoose ?
  • 你如何在mongoose中实现模式中的价格范围?

1 个解决方案

#1


2  

My solution

I decided to have both values in my Schema separately, like in the example bellow:

我决定在我的Schema中分别使用这两个值,如下面的示例所示:

income: {
    currency: { type: String },
    range: {
        min: { type: Number, min: 0 },
        max: { type: Number, min: 0 }
    }
}

Problem

However, now I am left with a problem. How to check that my MAX >= MIN at all times, and that MIN <= MAX ??

但是,现在我有一个问题。如何检查我的MAX> = MIN,并且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.

鉴于MIN和MAX都是强制性的,可以有一个只有较高范围的对象,或者只有较低的对象。

Enter Custom Validators

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:

验证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!"
}

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!"
}

Final result

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!"
            }
        }
    }
}

Going further

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.

这个解决方案很好,展示了先进的知识并满足了要求。在尝试插入MIN> MAX的对象时,如果插入了VALUE,您将收到一条很好的错误消息。

However, I have the following questions / suggestions for improvement, that I didn't add because I don't yet know how to do:

但是,我有以下问题/改进建议,我没有添加,因为我还不知道该怎么做:

  1. 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:

    验证器将阻止插入不一致的对象。但是,当它不能防止错误的UPDATES时,即,以下示例将对MIN = 10的对象起作用:

    ObjModel.update( { _id: "58dd26b5476664e33eec4b93" }, { $set: {"income.range.max": 1}} );

    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.

要使用验证程序对对象进行更新,必须使用save方法,并遵循mongoose docs末尾描述的约定。

Model.findOne({ name: 'borne' }, function (err, doc){
  doc.name = 'jason borne';
  doc.visits.$inc();
  doc.save();
});

Which will trigger the validator as expected.

这将按预期触发验证器。

  1. In the functions to check MIN and MAX, you can print the value being evaluated using {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.
  2. 在检查MIN和MAX的功能中,您可以使用{VALUE}打印要评估的值。但是,您可以使用该对象的其他值吗?比较MIN和MAX时,打印被评估的值以及要比较的值将非常有用。

Hope it helps, and inspires!

希望它有所帮助,并激发灵感!

#1


2  

My solution

I decided to have both values in my Schema separately, like in the example bellow:

我决定在我的Schema中分别使用这两个值,如下面的示例所示:

income: {
    currency: { type: String },
    range: {
        min: { type: Number, min: 0 },
        max: { type: Number, min: 0 }
    }
}

Problem

However, now I am left with a problem. How to check that my MAX >= MIN at all times, and that MIN <= MAX ??

但是,现在我有一个问题。如何检查我的MAX> = MIN,并且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.

鉴于MIN和MAX都是强制性的,可以有一个只有较高范围的对象,或者只有较低的对象。

Enter Custom Validators

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:

验证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!"
}

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!"
}

Final result

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!"
            }
        }
    }
}

Going further

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.

这个解决方案很好,展示了先进的知识并满足了要求。在尝试插入MIN> MAX的对象时,如果插入了VALUE,您将收到一条很好的错误消息。

However, I have the following questions / suggestions for improvement, that I didn't add because I don't yet know how to do:

但是,我有以下问题/改进建议,我没有添加,因为我还不知道该怎么做:

  1. 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:

    验证器将阻止插入不一致的对象。但是,当它不能防止错误的UPDATES时,即,以下示例将对MIN = 10的对象起作用:

    ObjModel.update( { _id: "58dd26b5476664e33eec4b93" }, { $set: {"income.range.max": 1}} );

    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.

要使用验证程序对对象进行更新,必须使用save方法,并遵循mongoose docs末尾描述的约定。

Model.findOne({ name: 'borne' }, function (err, doc){
  doc.name = 'jason borne';
  doc.visits.$inc();
  doc.save();
});

Which will trigger the validator as expected.

这将按预期触发验证器。

  1. In the functions to check MIN and MAX, you can print the value being evaluated using {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.
  2. 在检查MIN和MAX的功能中,您可以使用{VALUE}打印要评估的值。但是,您可以使用该对象的其他值吗?比较MIN和MAX时,打印被评估的值以及要比较的值将非常有用。

Hope it helps, and inspires!

希望它有所帮助,并激发灵感!