あなたのコードはいくつかのエラーケースを処理せず、間違ったfind
を使用していますが 機能、一般的なフローはあなたがやりたい仕事を与える典型的なものです。
- 重複以外のエラーがある場合、コールバックは呼び出されません。これにより、NodeJsアプリケーションでダウンストリームの問題が発生する可能性があります
-
findOne
を使用しますfind
ではなく キーが一意である場合、結果は1つだけになるためです。それ以外の場合は、配列を返します。 - コールバックが従来の
error
を予期していた場合 最初の引数として、コールバックをfindOne
に直接渡すことができます 匿名関数を導入するのではなく、関数。 -
findOneAndUpdate
もご覧ください。 最終的には、最終的なスキーマとロジックがどうなるかによって異なります。
前述のように、findOneAndUpdate
を使用できる場合があります 、ただし追加費用がかかります。
function save(id, title, callback) {
Value.findOneAndUpdate(
{id: id, title: title}, /* query */
{id: id, title: title}, /* update */
{ upsert: true}, /* create if it doesn't exist */
callback);
}
もちろんコールバックはまだありますが、重複が見つかった場合はデータが再度書き込まれます。それが問題であるかどうかは、実際にはユースケースに依存します。
私はあなたのコードを少しクリーンアップしました...しかしそれは本当に非常に単純で、コールバックは明確でなければなりません。 callback
この関数は、常に新しく保存されたドキュメントまたは重複として一致したドキュメントのいずれかを受け取ります。 saveNewValue
を呼び出す関数の責任です エラーをチェックして適切に処理します。エラーの種類に関係なくコールバックが呼び出され、常に一貫した方法で結果とともに呼び出されることを確認した方法もわかります。
function saveNewValue(id, title, callback) {
if (!callback) { throw new Error("callback required"); }
var thisValue = new models.Value({
id:id,
title:title //this is a unique value
});
thisValue.save(function(err, product) {
if (err) {
if (err.code === 11000) { //error for dupes
return models.Value.findOne({title:title}, callback);
}
}
callback(err, product);
});
}
または、promise を使用することもできます。 パターン。この例では、when.js を使用しています。 。
var when = require('when');
function saveNewValue(id, title) {
var deferred = when.defer();
var thisValue = new models.Value({
id:id,
title:title //this is a unique value
});
thisValue.save(function(err, product) {
if (err) {
if (err.code === 11000) { //error for dupes
return models.Value.findOne({title:title}, function(err, val) {
if (err) {
return deferred.reject(err);
}
return deferred.resolve(val);
});
}
return deferred.reject(err);
}
return deferred.resolve(product);
});
return deferred.promise;
}
saveNewValue('123', 'my title').then(function(doc) {
// success
}, function(err) {
// failure
});