Nodejs又一个mongoose的问题,字段。

Nodejs又一个mongoose的问题,字段。

我在写注册的时候是这样的:

var User= new Schema({
    username: { type: String, required: true, index: { unique: true } },
    password: { type: String, required: true }, 
    email: { type:String, required: true}
});

User.methods.comparePasswod = fn;

但是我登录的时候不用写上email,但是这里却设了required: true。怎么办啊?


4 回复

当然可以!根据你的描述,你在设计用户模型时希望在注册时需要提供 usernameemail,但在登录时只需要提供 username 或其他唯一标识符(例如 email)。为了实现这一点,我们可以稍微调整一下模型的设计,并引入一些额外的逻辑来处理登录。

解决方案

  1. 移除 emailrequired 属性:你可以将 email 字段设置为可选的,这样在注册时可以不提供 email
  2. 引入 loginField:我们可以定义一个字段来指定用于登录的唯一标识符,既可以是 username 也可以是 email

示例代码

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

// 定义用户模型
const UserSchema = new Schema({
    username: { type: String, required: true, index: { unique: true } },
    password: { type: String, required: true },
    email: { type: String } // 设置为可选
});

// 定义一个方法来检查密码是否匹配
UserSchema.methods.comparePassword = function (password) {
    return this.password === password;
};

// 定义一个方法来获取登录字段
UserSchema.statics.getLoginField = function () {
    return ['username', 'email'];
};

// 创建模型
const User = mongoose.model('User', UserSchema);

module.exports = User;

解释

  1. 移除 emailrequired 属性

    email: { type: String } // 设置为可选
    
  2. 添加 comparePassword 方法

    UserSchema.methods.comparePassword = function (password) {
        return this.password === password;
    };
    
  3. 添加 getLoginField 静态方法

    UserSchema.statics.getLoginField = function () {
        return ['username', 'email'];
    };
    

登录逻辑

在实际的登录逻辑中,你可以使用 getLoginField 方法来动态选择用于验证的字段:

async function login(usernameOrEmail, password) {
    const User = require('./models/User'); // 假设 User 模型在这里
    const loginFields = User.getLoginField();

    for (const field of loginFields) {
        const user = await User.findOne({ [field]: usernameOrEmail });
        if (user && user.comparePassword(password)) {
            return user; // 登录成功
        }
    }

    throw new Error('Invalid credentials'); // 登录失败
}

通过这种方式,你可以在注册时提供 usernameemail,而在登录时只需提供 usernameemail 中的一个。


有关系么

不好意思,我发现很多都不是问题。是其他问题引起,新手就是这样,我写代码的时候都感觉像瞎子一样,所以有不懂就怕

在你的注册逻辑中,设置了 email 字段为必填项 (required: true)。然而,在登录时你并不需要用户提供 email。你可以通过两种方法来解决这个问题:

  1. 删除 required 验证:如果你在某些情况下不需要 email 字段(例如在登录时),可以删除 required 验证。
var UserSchema = new Schema({
    username: { type: String, required: true, index: { unique: true } },
    password: { type: String, required: true }, 
    email: { type: String }
});

var User = mongoose.model('User', UserSchema);
  1. 使用条件验证:你可以自定义验证函数,根据不同的操作(如注册或登录)来决定是否验证 email 字段。
var UserSchema = new Schema({
    username: { type: String, required: true, index: { unique: true } },
    password: { type: String, required: true }, 
    email: { type: String }
}, {
    validateBeforeSave: true // 确保在保存前进行验证
});

// 自定义验证逻辑
UserSchema.path('email').validate(function(value, next) {
    if (this.isNew || this.isModified('email')) {
        if (!value) {
            return next(false);
        }
    }
    next(true);
}, 'Email is required');

var User = mongoose.model('User', UserSchema);

示例代码

假设你有一个用户模型,并且你希望在注册时验证 email 字段,但在登录时可以忽略它。

const mongoose = require('mongoose');
const bcrypt = require('bcrypt');

const UserSchema = new mongoose.Schema({
    username: { type: String, required: true, index: { unique: true } },
    password: { type: String, required: true },
    email: { type: String }
}, {
    validateBeforeSave: true
});

UserSchema.path('email').validate(function(value, next) {
    if (this.isNew || this.isModified('email')) {
        if (!value) {
            return next(false);
        }
    }
    next(true);
}, 'Email is required');

UserSchema.methods.comparePassword = function(password, callback) {
    bcrypt.compare(password, this.password, function(err, isMatch) {
        if (err) return callback(err);
        callback(null, isMatch);
    });
};

const User = mongoose.model('User', UserSchema);

module.exports = User;

这样,你可以在注册时强制验证 email 字段,而在登录时可以选择不提供 email

回到顶部