即使我为必填字段提供了值,猫鼬验证仍失败

时间:2018-07-22 21:01:41

标签: node.js mongodb mongoose mongoose-schema

我有以下模型:

/**
 * @module optikos
 */
const mongoose = require('mongoose');

/**
 * Define the schema of the main table(Document)
 * Needs to be redefined to add user role here
 */
const dbUri = 'mongodb://localhost:27017/optikosmaindb';
mongoose.connect(dbUri,{ useNewUrlParser: true });
const optikosSchema = mongoose.Schema({
    name: {
        type: String
    },
    email: {
        type: String,
        required:[true,'Email is required']
    },
    password: {
        type: String,
        required:[true,'Password is required']
    },
    dbpath: {
        type: String,
        required:true
    },
    role:{
        type:String,
        lowercase:true,
        enum:{
            values:['admin','employee','shop owner'],
            message:'`${VALUE} is not a valid role`'
        },
        default:'shop owner'
    },
    payment_status: {
        /***
         * Only show owners need to have a payment status
         */
        required:this.role == 'shop owner',
        type: String,
        lowercase:true,
        enum:{
            values:['pending','paid'],
            message:'`{VALUE} is not a valid payment status`'
        },
        default: 'pending' //will change to paid once a payment transaction is completed

    },
    payment_reset: {
        required:this.role == 'shop owner',
        type: Date,
        default:Date.now
    }
});

const Optikos = mongoose.model('optikos',optikosSchema);
module.exports = Optikos;

我还有一个名为index.js的文件,在其中需要这样的文件才能为我的数据库创建一些用户:

const admins = require('./admins');
const Optikos = require('../schemas/optikos');
const bcrypt = require('bcrypt');
async function setup() {
    console.log('Setting app Optikos main database');

    try {

        let registeredAdmins = admins.map(async admin=>{
            let {email,name,password} = admin;
            let role = 'admin';
            let saltRounds = 10;
            password = await bcrypt.hash(password,saltRounds);

            let dbpath = dbUri;
            let user = new Optikos({
                'name':name,
                'email':email,
                'password':password,
                'role':role,
                'dbpath':dbpath
            });

            return user;
        });
        let response  = await Optikos.create(registeredAdmins);
        console.log('Registered admins')
        process.exit(0);
    } catch (e) {
        console.log('Error error error')
        console.log(e)
        process.exit(1)
    }

}

setup();

admins文件是包含名称,电子邮件和密码字段的对象数组。但是,在尝试运行index文件后,我得到以下信息:“ {ValidationError:optikos验证失败:dbpath:Path {{ 1}}是必需的。,密码:需要密码,电子邮件:需要电子邮件”。但是,如果我记录了要传递给“ new Optikos()”的所有变量,则会得到期望的值。这是怎么回事?

2 个答案:

答案 0 :(得分:1)

我通过执行以下操作解决了必填字段错误:

let registeredAdmins = admins.map(async admin=>{
            let {email,name,password} = admin;
            let role = 'admin';
            let saltRounds = 10;
            password = await bcrypt.hash(password,saltRounds);

            let dbpath = dbUri;
            let user = new Optikos({
                'name':name,
                'email':email,
                'password':password,
                'role':role,
                'dbpath':dbpath
            });

            return user;
        });
        Promise.all(registeredAdmins)
        .then(async users=>{
            console.log(users)
            await Optikos.create(users);
            console.log('Yeap')
        }).catch(e=>{
            console.log(e)
        })

由于registeredAdmins是一个promise列表,因此我使用Promise.all()来获取已解决promise的值。感谢@AbdullahDibas作为提示

答案 1 :(得分:0)

通常是由于async await在经常循环的情况下无法按预期的方式工作的事实(尽管for-await-in的另一种替代方法是,但仍未被认为是可以保证生产安全,或符合某些eslint标准的良好做法),因此,您可能希望将代码改写为:

const admins = require('./admins');
const Optikos = require('../schemas/optikos');
const bcrypt = require('bcrypt');

async function setup() {
    console.log('Setting app Optikos main database');
    const passwordPromises = [];
    try {

        admins.forEach(admin => {
            let { password } = admin;
            let saltRounds = 10;
            passwordPromises.push(bcrypt.hash(password, saltRounds));
        });

        const passwords = await Promise.all(passwordPromises);

        let registeredAdmins = admins.map((admin, index) => {
            let { email, name } = admin;
            let user = new Optikos({
                'name': name,
                'email': email,
                // The below would work because Promise.all resolves them in
                // the sequential order. Also, since there would be a one - to - one
                // mapping in the indices of the admins and the password due to the above stated fact
                // the following would work
                'password': passwords[index],
                'role': 'admin',
                'dbpath': dbUri
            });
            return user;
        });

        let response = await Optikos.create(registeredAdmins);
        console.log('Registered admins')
        process.exit(0);
    } catch (e) {
        console.log('Error error error')
        console.log(e)
        process.exit(1)
    }

}