Mongooseの既存のエントリのフィールドを変更するには、使用することの違いは何ですか
model = new Model([...])
model.field = 'new value';
model.save();
この
Model.update({[...]}, {$set: {field: 'new value'});
私がこの質問をしている理由は、昨日投稿した問題に対する誰かの提案のためです: NodeJSとMongo-複数のユーザーが同時にリクエストを送信するときの予期しない動作 。その人は、保存の代わりに更新を使用することを提案しましたが、なぜそれが違いを生むのか完全にはわかりません。
ありがとう!
最初に2つの概念。アプリケーションはClient、MongodbはServerです。
主な違いは、.save()
を使用すると、すでにクライアント側コードにオブジェクトがあるか、書き戻す前にサーバーからデータを取得する必要があり、すべてを書き戻すことです。
一方、.update()
は、サーバーからクライアントにデータをロードすることをnot必要とします。すべての対話はクライアントに取得せずにサーバー側で行われます。したがって、既存のドキュメントにコンテンツを追加する場合、.update()
はこの方法で非常に効率的になります。
さらに、multi
パラメータが.update()
にあり、クエリ条件に一致する複数のドキュメントでアクションを実行できます。
.update()
を呼び出しとして使用するときに失う便利なメソッドにはいくつかのものがありますが、特定の操作の利点は、負担する必要がある「トレードオフ」です。これと使用可能なオプションの詳細については、 documentation を参照してください。
要するに、.save()
はクライアント側のインターフェースであり、.update()
はサーバー側です。
いくつかの違い:
update
はfind
の後にsave
が続くよりも効率的です。これは、ドキュメント全体の読み込みを回避するためです。update
はMongoDB update
に変換されますが、Mongoose save
はMongoDB insert
(新しいドキュメントの場合)またはupdate
。save
では、 Mongooseは内部的にドキュメントを差分します であり、実際に変更されたフィールドのみを送信することに注意することが重要です。これは原子性に適しています。update
が有効にできます。pre
およびpost
フック)は異なります。Mongooseにはミドルウェアと呼ばれる便利な機能があります。 「pre」および「post」ミドルウェアがあります。ミドルウェアは、「更新」中ではなく「保存」を行うと実行されます。たとえば、パスワードが変更されるたびにユーザースキーマでパスワードをハッシュする場合、preを使用して次のように実行できます。別の便利な例は、ドキュメントごとにlastModifiedを設定することです。ドキュメントは http://mongoosejs.com/docs/middleware.html にあります。
UserSchema.pre('save', function(next) {
var user = this;
// only hash the password if it has been modified (or is new)
if (!user.isModified('password')) {
console.log('password not modified');
return next();
}
console.log('password modified');
// generate a salt
bcrypt.genSalt(10, function(err, salt) {
if (err) {
return next(err);
}
// hash the password along with our new salt
bcrypt.hash(user.password, salt, function(err, hash) {
if (err) {
return next(err);
}
// override the cleartext password with the hashed one
user.password = hash;
next();
});
});
});
軽視してはならない1つの詳細:concurrency
前述したように、doc.save()
を実行するときは、最初にドキュメントをメモリにロードしてから変更し、最後にdoc.save()
MongoDBサーバーへの変更を行う必要があります。
ドキュメントがそのように編集されたときに問題が発生します同時に:
Model.updateOne()
のようなアトミック操作を実行する場合、同時性は問題ではありません。これは、特定の同時実行制御を実行するMongoDBサーバーで操作が完全に実行されるためです。
したがって、注意してください!