Mongoose:findOneAndUpdateが更新されたドキュメントを返さない


256

以下は私のコードです

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');

var Cat = mongoose.model('Cat', {
    name: String,
    age: {type: Number, default: 20},
    create: {type: Date, default: Date.now} 
});

Cat.findOneAndUpdate({age: 17}, {$set:{name:"Naomi"}},function(err, doc){
    if(err){
        console.log("Something wrong when updating data!");
    }

    console.log(doc);
});

私のmongoデータベースにはすでにいくつかのレコードがあります。このコードを実行して、年齢が17歳の名前を更新し、結果をコードの最後に出力します。

しかし、なぜ変更された名前ではなく、コンソールから同じ結果が得られるのですか。ただし、mongo dbコマンドラインに移動して「db.cats.find();」その結果、名前が変更されました。

次に、このコードを再度実行して結果を変更します。

私の質問は次のとおりです。データが変更された場合、なぜconsole.logで最初のデータを取得したのですか。

回答:


527

なぜこれが起こるのですか?

デフォルトは返すことです元、変更されていない文書を。新しく更新されたドキュメントを返す場合は、追加の引数を渡す必要があります。newプロパティがに設定されたオブジェクトtrueです。

マングースのドキュメントから:

Query#findOneAndUpdate

Model.findOneAndUpdate(conditions, update, options, (error, doc) => {
  // error: any errors that occurred
  // doc: the document before updates are applied if `new: false`, or after updates if `new = true`
});

利用可能なオプション

  • new:bool- trueの場合、元のドキュメントではなく変更されたドキュメントを返します。デフォルトはfalse(4.0で変更)

解決

{new: true}更新した結果をdoc変数に入れたい場合は渡します。

//                                                         V--- THIS WAS ADDED
Cat.findOneAndUpdate({age: 17}, {$set:{name:"Naomi"}}, {new: true}, (err, doc) => {
    if (err) {
        console.log("Something wrong when updating data!");
    }

    console.log(doc);
});

15
これは私には壊れているように見えますが、それでも古いドキュメントをnew:trueで返します。
PDN

@PDNどのバージョンのmongoose / mongoをお持ちですか?それはそれがどのように機能するかを混乱させているかもしれません。
Cole Erickson

5
あなたはすでに新しいドキュメントにアクセスできるので、私には意味があります
danday74

3
それは私のために働いた、私はmoogoseバージョン4.6.3を使用している、ありがとう
cesar andavisa

2
NodeJs MongoDBのネイティブの用途-{ returnOriginal: false }
ニックGrealy

78

Mongooseの代わりにNode.jsドライバーを使用している場合は、の{returnOriginal:false}代わりに使用する必要があります{new:true}


1
ありがとうございました!これは私にとって機能しますmongodbノードバージョン2.2.27
Kevin Ng

6
これは、ばかAPIの一種です。MongooseにネイティブAPIと同じ署名を使用しないのはなぜですか?デフォルトで更新されたドキュメントを返さないのはなぜですか?マングースは、私が毎日使用しているいらいらさせるライブラリの1つです。
Askdesigners

56

したがって、「findOneAndUpdate」には、元のドキュメントを返すオプションが必要です。そして、オプションは:

MongoDBシェル

{returnNewDocument: true}

参照:https : //docs.mongodb.com/manual/reference/method/db.collection.findOneAndUpdate/

マングース

{new: true}

参照: http //mongoosejs.com/docs/api.html#query_Query-findOneAndUpdate

Node.js MongoDBドライバーAPI:

{returnOriginal: false}

参照:http : //mongodb.github.io/node-mongodb-native/3.0/api/Collection.html#findOneAndUpdate


Laravel:'returnDocument' => FindOneAndUpdate::RETURN_DOCUMENT_AFTER
ジャコモアルゼッタ

39

デフォルトでは、findOneAndUpdateは元のドキュメントを返します。変更されたドキュメントを返す場合は、オプションオブジェクト{ new: true }を関数に渡します。

Cat.findOneAndUpdate({ age: 17 }, { $set: { name: "Naomi" } }, { new: true }, function(err, doc) {

});

2
なぜ_idnullなのですか?
曲がりくねった

14

ネイティブプロミスでES6 / ES7スタイルを使用してこれに遭遇した人のために、ここにあなたが採用できるパターンがあります...

const user = { id: 1, name: "Fart Face 3rd"};
const userUpdate = { name: "Pizza Face" };

try {
    user = await new Promise( ( resolve, reject ) => {
        User.update( { _id: user.id }, userUpdate, { upsert: true, new: true }, ( error, obj ) => {
            if( error ) {
                console.error( JSON.stringify( error ) );
                return reject( error );
            }

            resolve( obj );
        });
    })
} catch( error ) { /* set the world on fire */ }

15
コールバック関数を提供しない場合、MongooseはPromiseを返します。独自の約束をする必要はありません!
joeytwiddle 2017

1
@joeytwiddle Mongoose 、コールバックを提供しない場合、Promiseを返しません。代わりに、Promise APIの小さなサブセットのみを提供するQueryオブジェクトを返します。これは、Mongooseのドキュメントによるものです。
ジェイミーライディング

13

これはの更新されたコードですfindOneAndUpdate。できます。

db.collection.findOneAndUpdate(    
  { age: 17 },      
  { $set: { name: "Naomi" } },      
  {
     returnNewDocument: true
  }    
)

9

マングースメンテナーはこちら。newオプションをtrue(または同等returnOriginalfalse)に設定する必要があります

await User.findOneAndUpdate(filter, update, { new: true });

// Equivalent
await User.findOneAndUpdate(filter, update, { returnOriginal: false });

MongooseのfindOneAndUpdate()ドキュメントMongooseでのドキュメントの更新に関するこのチュートリアルを参照してください。


新規ではなくreturnNewDocumentを誤って記述しました。手伝ってくれてありがとう!
user1111527

3

変更されたドキュメントを返したい{new:true}場合は、使用できるオプションAPIリファレンスを設定する必要がありますCat.findOneAndUpdate(conditions, update, options, callback) // executes

公式のMongoose API http://mongoosejs.com/docs/api.html#findoneandupdate_findOneAndUpdateによって取得され、次のパラメーターを使用できます

A.findOneAndUpdate(conditions, update, options, callback) // executes
A.findOneAndUpdate(conditions, update, options)  // returns Query
A.findOneAndUpdate(conditions, update, callback) // executes
A.findOneAndUpdate(conditions, update)           // returns Query
A.findOneAndUpdate()                             // returns Query

別の実装thatsは公式のAPIページでは表現されていませんが、私が使用したいのは、さまざまなエラーをすべて処理できる場所に配置できるPromise基本実装です.catch

    let cat: catInterface = {
        name: "Naomi"
    };

    Cat.findOneAndUpdate({age:17}, cat,{new: true}).then((data) =>{
        if(data === null){
            throw new Error('Cat Not Found');
        }
        res.json({ message: 'Cat updated!' })
        console.log("New cat data", data);
    }).catch( (error) => {
        /*
            Deal with all your errors here with your preferred error handle middleware / method
         */
        res.status(500).json({ message: 'Some Error!' })
        console.log(error);
    });

2

以下に、mongooseのクエリを示しますfindOneAndUpdate。ここnew: trueは、更新されたドキュメントを取得するために使用され、fieldsために使用され、特定のフィールドを取得するために使用されます。

例えば。 findOneAndUpdate(conditions, update, options, callback)

await User.findOneAndUpdate({
      "_id": data.id,
    }, { $set: { name: "Amar", designation: "Software Developer" } }, {
      new: true,
      fields: {
        'name': 1,
        'designation': 1
      }
    }).exec();

1

私はすでに遅れていますが、ここに簡単で実用的な答えを追加しましょう

const query = {} //your query here
const update = {} //your update in json here
const option = {new: true} //will return updated document

const user = await User.findOneAndUpdate(query , update, option)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.