Как отловить ошибку при вставке документа MongoDB, нарушающего уникальный индекс?

Я создаю приложение MEAN.

Это моя схема имени пользователя, имя пользователя должно быть уникальным.

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

module.exports = mongoose.model('User', new Schema({ 
    username: { type: String, unique: true }
}));

На моем маршруте публикации я сохраняю пользователя следующим образом:

app.post('/authenticate', function(req, res) {
        var user = new User({
            username: req.body.username
        });

        user.save(function(err) {
            if (err) throw err;

            res.json({
                success: true
            });

        });
    })

Если я снова отправлю сообщение с тем же именем пользователя, я получу эту ошибку:

MongoError: insertDocument :: вызвано :: 11000 E11000 индекс ошибки повторяющегося ключа:

Может кто-нибудь объяснить, как вместо ошибки отправить json типа { succes: false, message: 'User already exist!' }

Примечание: после того, как я отправлю пользователя, я автоматически выполню аутентификацию, мне не нужен пароль или что-то еще.


person Hiero    schedule 02.06.2015    source источник


Ответы (3)


Вам нужно будет проверить ошибку, возвращаемую методом сохранения, чтобы увидеть, не возникла ли она из-за повторяющегося имени пользователя.

app.post('/authenticate', function(req, res) {
  var user = new User({
    username: req.body.username
  });

  user.save(function(err) {
    if (err) {
      if (err.name === 'MongoError' && err.code === 11000) {
        // Duplicate username
        return res.status(422).send({ succes: false, message: 'User already exist!' });
      }

      // Some other error
      return res.status(422).send(err);
    }

    res.json({
      success: true
    });

  });
})
person Jason Cust    schedule 02.06.2015
comment
500 не следует использовать в качестве кода состояния, поскольку это не внутренняя ошибка сервера. Таким образом, вы можете использовать 400 для конфликта данных. - person Deva; 27.06.2019
comment
Эта обработка бесполезна, если у вас более одного уникального поля, потому что оно всегда возвращает один и тот же код ошибки. - person krekto; 04.07.2019
comment
Что делать, если в документе есть два уникальных поля? Как бы дать четкое сообщение, какое поле вызывает ошибку. Например: у нас может быть User с адресом электронной почты и полем псевдонима, которые должны быть уникальными? - person Prajeet Shrestha; 24.07.2019

Вы также можете попробовать этот хороший пакет mongoose-unique-validator , что значительно упрощает обработку ошибок, поскольку при попытке нарушить уникальное ограничение вы получите ошибку проверки Mongoose, а не ошибку E11000 от MongoDB:

var mongoose = require('mongoose');
var uniqueValidator = require('mongoose-unique-validator');

// Define your schema as normal.
var userSchema = mongoose.Schema({
    username: { type: String, required: true, unique: true }
});

// You can pass through a custom error message as part of the optional options argument:
userSchema.plugin(uniqueValidator, { message: '{PATH} already exists!' });
person chridam    schedule 02.06.2015

Попробуй это:

app.post('/authenticate', function(req, res) {
        var user = new User({
            username: req.body.username
        });

        user.save(function(err) {
            if (err) {
                // you could avoid http status if you want. I put error 500 
                return res.status(500).send({
                    success: false,
                    message: 'User already exist!'
                });
            }

            res.json({
                success: true
            });

        });
    })
person Jose Mato    schedule 02.06.2015
comment
Спасибо, работает как исключение, я думал об этом, но я думал, что эта ошибка может вернуть что-то еще, кроме существующей ошибки пользователя, я ошибаюсь? - person Hiero; 02.06.2015
comment
Да, но это обычный случай: попробуйте сохранить пользователя, и если возникла ошибка, вы думаете, что пользователь дублирован. Вы можете показать пользователю простое сообщение о том, что пользователь уже существует, а затем сохранить в журналах настоящую ошибку, чтобы увидеть, есть ли ошибки с базой данных. - person Jose Mato; 02.06.2015
comment
Не рекомендуется, следует выполнять специальную обработку ошибок. Код ошибки и сообщение об ошибке следует как минимум обработать. - person Diego Gallegos; 09.11.2018
comment
Согласитесь, Диего Гальегос, для производственного варианта использования всегда рекомендуется обрабатывать логические и операционные ошибки, это не та же запись, которая не найдена, чем база данных не может подключиться / тайм-аут / что угодно - person Jose Mato; 09.11.2018
comment
лучше с попыткой поймать и прочитать номер ошибки - person Marco Pestrin; 10.03.2021
comment
Полностью согласен, Марко, упрощать вещи не обязательно, но чтобы действительно знать ошибку, которую возвращает MongoDB, лучше проверить числовой код, как вы указали. - person Jose Mato; 11.03.2021