Mongoose.js Уникальная проверка - PullRequest
0 голосов
/ 23 сентября 2019

ПРИМЕЧАНИЕ: в нижней части вопроса есть правка:

Могу ли я проверить уникальность базы данных, используя либо специальный валидатор, либо предварительно подключенный файл модели Mongoose.js.Я знаю, что могу проверить это в контроллере, но я бы предпочел поместить его в файл модели с остальными валидаторами только для согласованности.

Мне также известно, что существует пакет npm, называемый mongoose-unique-validator, который делает это, но я не фанат установки библиотеки, которая должна выполнять от одной до пяти строк кода.

Mongoose также обладает свойством «уникальности», которое выдает ошибку, если элемент не уникален.Но в их документах четко указано, что это не валидатор.И выдаваемая ошибка не маршрутизируется так же, как ошибки проверки.

Здесь приведены соответствующие части файла модели.Это проверит БД, и если нет dup, то он создаст статью, но если есть dup, он выдаст ошибку, но не ошибку проверки, что я и хочу.Если я просто возвращаю false при наличии дубликата, он просто игнорирует проверку и создает дубликат статьи.Это, без сомнения, связано с Promises / Async.Вот соответствующие документы Mongoose https://mongoosejs.com/docs/validation.html#async-custom-validators. И они говорят о том, что уникальное свойство не является валидатором https://mongoosejs.com/docs/faq.html.

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

const articleSchema = new Schema({
  title: {
    type: String,
    required: [true, "Title is required"],
    // unique: true, 
    // isAsync: true,
    validate: {
      validator: function(value) {
        this.constructor.findOne({title: value}, (err, article) => {
          if (err || !article) { 
            return true;
          } else {
            // return false;
            throw new Error('Duplicate');
          }
        });
      },
      message: (props) => `Title "${props.value}" is already in use.`
    },
  },
  content: { type: String, required: true }
});

РЕДАКТИРОВАТЬ: Я понял это, но это только работаетпри создании новой статьи, а не об обновлениях.Таким образом, вопрос все еще остается открытым, но основное внимание уделяется тому, как заставить его работать над обновлениями.При обновлении Mongoose не обрабатывает «this» как объект документа, как при создании.Вместо этого "this" является объектом запроса, а "this.constructor.findOne ()" выдает ошибку "this.constructor.findOne не является функцией".Вот исправленный валидатор:

  title: {
    type: String,
    required: [true, "Title is required"],
    isAsync: true,
    validate: {
      validator: async function(value) {
        const article = await this.constructor.findOne({title: value});
        if (article) {
          throw new Error(`${value} is already in use.`);
        }
      }
    }
  }

1 Ответ

0 голосов
/ 23 сентября 2019

Ваша validator функция будет только запускать сценарий и не передавать обратный вызов или обещание mongoose, поэтому mongoose предполагает, что валидатор вернет true и продолжит процесс.Согласно документу, вы должны вернуть обещание или использовать обратный вызов.

Обещание:

validator: function(value) {
    var here = this;
    return new Promise(function(resolve, reject) {
        here.constructor.findOne({title: value}, (err, article) => {
        if (err || !article) { 
          resolve(true);
        } else {
          resolve(false);
        }
      });
    })
}

Обратный вызов: (необходимо установить isAsync: true)

validator: function(value, cb) {
      this.constructor.findOne({title: value}, (err, article) => {
        if (err || !article) { 
          cb(true);
        } else {
          cb(false, "Content is used");
        }
     });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...