70

私はこのコードを持っています

var ClientSchema = new Schema({
  name: {type: String, required: true, trim: true}
});

var Client = mongoose.model('Client', ClientSchema);

Expressを使用して、このコードで新しいクライアントを作成します

var client = new Client(req.body);
client.save(function(err, data) {
  ....
});

フォームの名前フィールドを空のままにすると、スキーマで必要に応じて設定したため、mongooseはクライアントを作成できません。また、名前の前後にスペースを残すと、mongooseは保存する前にそのスペースを削除します。

今、私はこのコードでクライアントを更新しようとしています

var id = req.params.id;
var client = req.body;
Client.update({_id: id}, client, function(err) {
  ....
});

名前を変更できますが、フォームで空のままにすると、mongooseは空の名前を検証して保存しません。名前の前後に空のスペースを追加すると、名前がスペースとともに保存されます。

なぜマングースは保存時に検証するが更新には検証しないのですか?私はそれを間違った方法でやっていますか?

mongodb:2.4.0マングース:3.6.0エクスプレス:3.1.0ノード:0.10.1

4

7 に答える 7

100

Mongoose 4.0以降、新しいフラグでバリデーターを実行できますupdate()findOneAndUpdate()runValidators: true

Mongoose 4.0には、バリデーターを実行するオプションupdate()findOneAndUpdate()呼び出しが導入されています。このオプションをオンにすると、update()呼び出しが試行するすべてのフィールドに対してバリデーターが実行され$setます$unset

たとえば、OPのスキーマが与えられた場合:

const ClientSchema = new Schema({
  name: {type: String, required: true, trim: true}
});

const Client = mongoose.model('Client', ClientSchema);

更新ごとにフラグを渡す

次のように新しいフラグを使用できます。

const id = req.params.id;
const client = req.body;
Client.update({_id: id}, client, { runValidators: true }, function(err) {
  ....
});

preフックにフラグを使用する

何かを更新するたびにフラグを設定したくない場合は、次のpreフックを設定できfindOneAndUpdate()ます。

// Pre hook for `findOneAndUpdate`
ClientSchema.pre('findOneAndUpdate', function(next) {
  this.options.runValidators = true;
  next();
});

そうすれば、毎回フラグupdate()を渡すことなくバリデーターを使用できます。runValidators

于 2015-04-05T17:20:32.543 に答える
75

あなたは何も悪いことをしてvalidationいません。Mongoose内の内部ミドルウェアとして実装されてupdateおり、基本的にネイティブドライバーへのパススルーであるため、ミドルウェアは実行されません。

クライアントの更新を検証する場合はfind、オブジェクトを更新し、新しいプロパティ値をオブジェクトに適用して(アンダースコアのextendメソッドを参照)、それを呼び出す必要saveがあります。

Mongoose4.0アップデート

コメントとvictorkohlの回答に記載されているように、Mongooseは、呼び出しにオプションを含めると、$set$unset演算子のフィールドの検証をサポートするようになりました。runValidators: trueupdate

于 2013-03-26T04:38:50.683 に答える
12

MongoDBは、デフォルトでは更新に対して検証を実行しません。

更新が発生したときにデフォルトで検証を機能させるために、MongoDBに接続する直前に、次のようなものだけをグローバル設定に設定できます。

mongoose.set('runValidators', true); // here is your global setting

mongoose.connect(config.database, { useNewUrlParser: true });
mongoose.connection.once('open', () => {
    console.log('Connection has been made, start making fireworks...');
}).on('error', function (error) {
    console.log('Connection error:', error);
});

したがって、組み込みまたはカスタムの検証は、すべての更新で実行されます

于 2018-12-19T17:13:09.747 に答える
1

マングースの設定にこのオプションを追加すると、次のように機能します。

mongoose.set('runValidators', true)
于 2020-10-13T01:42:20.020 に答える
1

オプションを設定することにより、更新中に検証を実行できますrunValidators: true

例1:


const Kitten = db.model('Kitten', kittenSchema);

const update = { color: 'blue' };
const opts = { runValidators: true };
Kitten.updateOne({}, update, opts, function() {
  // code
});

例2:

const Kitten = db.model('Kitten', kittenSchema);

const update = { color: 'blue' };
const opts = { runValidators: true };
Kitten.updateOne(
  {
    _id: req.params.id
  },
  {
    $set: { ...update },
  },
  opts
).then(result => {
    // code
})

続きを読む:https ://mongoosejs.com/docs/validation.html#update-validators

于 2021-04-16T18:48:11.260 に答える
1

upsertオプションで使用すると、受け入れられた回答は機能しませんfindOneAndUpdatefindOneこれを回避する方法は、内部で、次に、updateOneまたは内部で実行するモデル静的メソッドを作成することcreateです。create検証を自動的に実行します。

export async function findOneAndUpdateWithValidation(
  this: LocationModel,
  filter: FilterQuery<LocationDocument>,
  update: UpdateQuery<LocationDocument>,
  options?: QueryOptions
) {
  const documentFound = await this.findOne(filter);
  
  if (!documentFound) return this.create(update);

  return this.updateOne(filter, update, options);
}

locationSchema.statics = {
  findOneAndUpdateWithValidation
}
于 2021-09-27T13:35:38.707 に答える
-1

あなたのモデルでは、例。Category.jsファイル:

const CategorySchema = mongoose.Schema({
category_name : {
type : String,
required : [true, 'Category Name Is Required !'],
trim : true,
maxlength : [30, 'Category Name Is To Long !'],
unique : true,
});
const Category = module.exports = mongoose.model("Category",CategorySchema);

ルートファイル内:

router.put("/",(req,res,next)=>{
  Category.findOneAndUpdate(
  {_id : req.body.categoryId},
  {$set : {category_name : req.body.category_name} },
  **{runValidators: true}**, function(err,result) {
    if(err){
      if(err.code === 11000){
       var duplicateValue = err.message.match(/".*"/);
       res.status(200).json({"defaultError":duplicateValue[0]+" Is Already Exsist !"});
       }else{
         res.status(200).json({"error":err.message} || {"defaultError":'Error But Not Understood !'});
       }
    }else{
     console.log("From category.js (Route File) = "+result);
     res.status(200).json({"success":"Category Updated Successfully!!"});
    }
});
于 2018-05-04T10:52:28.813 に答える