web-dev-qa-db-ja.com

Mongoose-存在しない場合はドキュメントを作成し、存在しない場合は更新-どちらの場合でもドキュメントを返す

私は自分のコードの一部をより短く、より簡単にリファクタリングする方法を探していますが、Mongooseをよく知らないので、どうすればいいかわかりません。

コレクションのドキュメントの存在を確認し、存在しない場合は作成します。存在する場合は、更新する必要があります。どちらの場合でも、後でドキュメントのコンテンツにアクセスする必要があります。

これまで何とかしてきたことは、特定のドキュメントのコレクションを照会し、見つからない場合は新しいドキュメントを作成することです。見つかった場合は、それを更新します(現在、日付をダミーデータとして使用しています)。そこから、最初のfind操作で見つかったドキュメントまたは新しく保存されたドキュメントにアクセスできますが、これは機能しますが、目的を達成するためのより良い方法が必要です。

これが私の作業用コードです。

var query = Model.find({
    /* query */
}).lean().limit(1);

// Find the document
query.exec(function(error, result) {
    if (error) { throw error; }
    // If the document doesn't exist
    if (!result.length) {
        // Create a new one
        var model = new Model(); //use the defaults in the schema
        model.save(function(error) {
            if (error) { throw error; }
            // do something with the document here
        });
    }
    // If the document does exist
    else {
        // Update it
        var query = { /* query */ },
            update = {},
            options = {};

        Model.update(query, update, options, function(error) {
            if (error) { throw error; }
            // do the same something with the document here
            // in this case, using result[0] from the topmost query
        });
    }
});

findOneAndUpdateおよびその他の関連メソッドを調べましたが、それらが私のユースケースに適合するかどうか、またはそれらを正しく使用する方法を理解しているかどうかはわかりません。誰かが私を正しい方向に向けることができますか?

(おそらく)関連する質問:


編集

私は検索で指摘された質問に出くわしませんでしたが、そこで答えを確認した後、私はこれを思いつきました。私の意見では確かにきれいで、うまくいきます。だから私が何かひどく間違ったことをしていない限り、私の質問はおそらく閉じられると思います。

私のソリューションに関する追加情報をいただければ幸いです。

// Setup stuff
var query = { /* query */ },
    update = { expire: new Date() },
    options = { upsert: true };

// Find the document
Model.findOneAndUpdate(query, update, options, function(error, result) {
    if (!error) {
        // If the document doesn't exist
        if (!result) {
            // Create it
            result = new Model();
        }
        // Save the document
        result.save(function(error) {
            if (!error) {
                // Do something with the document
            } else {
                throw error;
            }
        });
    }
});
47
Connor

newオプションパラメータを探しています。 newオプションは、新しく作成されたドキュメントを返します(新しいドキュメントが作成された場合)。次のように使用します。

var query = {},
    update = { expire: new Date() },
    options = { upsert: true, new: true, setDefaultsOnInsert: true };

// Find the document
Model.findOneAndUpdate(query, update, options, function(error, result) {
    if (error) return;

    // do something with the document
});

upsertはドキュメントが見つからない場合にドキュメントを作成するため、別のドキュメントを手動で作成する必要はありません。

86
user2441535

コードの一部をより短く簡単にリファクタリングしたいので、

  1. async / await を使用します
  2. .findOneAndUpdate() を使用してください answer

let query = { /* query */ };
let update = {expire: new Date()};
let options = {upsert: true, new: true, setDefaultsOnInsert: true};
let model = await Model.findOneAndUpdate(query, update, options);
5
Jossef Harush
///This is simple example explaining findByIDAndUpdate from my code added with try catch block to catch errors
try{
const options = {
            upsert: true,
            new: true,
            setDefaultsOnInsert: true
        };
        const query = {
            $set: {
                description: req.body.description,
                title: req.body.title
            }
        };
        const survey = await Survey.findByIdAndUpdate(
            req.params.id,
            query,
            options
        ).populate("questions");
}catch(e){
console.log(e)
}
0
Rahul Sadaphal