Как исправить проблему с добавлением необязательного уникального поля?

Когда пользователь регистрируется на сайте, указывать свой email ему необязательно. Но если все-таки указал, то этот email должен быть уникальным в базе. Вот фрагмент схемы:
const userSchema = new mongoose.Schema({
    username: {
        type: String,
        required: true,
    },
    name: {
        type: String,
        required: false,
    },
    email: {
        type: String,
        required: false,
        unique: true,
        lowercase: true,
    },

Проблема появляется тогда, когда пользователь не указывает свою почту, и из формы серверу приходит пустая строка. Тогда в моем коде получается, что первый же пользователь, не указавший свою почту, получает пустую строку в поле email. А так как поле email в БД должно быть уникальным для каждого пользователя, то других пользователей, не указавших почту, добавить не получится.
Исправить это я пытался так:
if (!email) {
    email = undefined;
}

но все равно получаю такую ошибку:
MongoError: E11000 duplicate key error collection: test.users index: email_1 dup key: { email: null }

Но разве undefined-значения не должны отбрасываться при записи в БД?
const newUser = await User.create({
			username,
			email,
			password
		});


Также хотел посоветоваться насчет этого фрагмента кода:
let query = User.find();
query = query.or([{ username }, { email }]);
query.projection("username email");
const result = await query;

if (result.some((e) => e.username === username)) {
    submitErrors.push("username_taken");
}

if (email && result.some((e) => e.email === email)) {
    submitErrors.push("email_taken");
}

Есть ли смысл делать что-то с query = query.or([{ username }, { email }]); для тех случаев, когда вместо email на сервер приходит пустая строка? Чтобы зря не искать по пустой строке?
  • Вопрос задан
  • 23 просмотра
Решения вопроса 1
Для поля email нужен разреженный индекс
{unique: true, sparse: true}

По второму вопросу, ищите с помощью findOne
и $or добавляете только если email существует
Что то типа такого:
let query = {username};
if (email) {
  query = {$or:[{username},{email}]}
}
User.findOne(query)
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы