2017-07-19 24 views
2

言う文書を上書きする私は、ドキュメントがあります。

{ 
    _id: 'some_mongodb_id', 
    name: 'john doe', 
    phone: '+12345678901', 
} 

私はこの文書を更新する:

.findOneAndUpdate({_id: 'some_mongodb_id'}, {name: 'Dan smith'}) 

そして結果はこのようになります。

{ 
    _id: 'some_mongodb_id', 
    name: 'Dan smith', 
} 

指定されていないプロパティは削除する必要があります。

どうすればよいですか?

+0

(findOneAndUpdateではなく)更新機能を使用しようとしましたか? –

+0

@ israel.zinc私は、違いはありません – stkvtflw

+0

@ israel.zincそしてそれは違いはありません。これは、標準ドライバがちょうどよい「アップデートオブジェクト」に['$ set'](https://docs.mongodb.com/manual/reference/operator/update/set/)を追加することによってこれを行う「mongoose」ですそのオブジェクトを「そのまま」通過させます。だから、この行動は、あなたが実際にそれを求めているように、それを動作させるためには、マングースのために "オフ"にする必要があります。 –

答えて

3

実際、mongooseが実際にはカバーの下でアップデートを「混乱させる」という事実のために、これは実際には通常のMongoDB関数への提出のデフォルトアクションです。

だから、mongooseは$set命令をここで発行することを意味する「推測」するための便利な方法として「賢明」とみなします。

const mongoose = require('mongoose'), 
     Schema = mongoose.Schema; 

mongoose.Promise = global.Promise; 
mongoose.set('debug',true); 

const uri = 'mongodb://localhost/test', 
     options = { useMongoClient: true }; 

const testSchema = new Schema({ 
    name: String, 
    phone: String 
}); 

const Test = mongoose.model('Test', testSchema); 

function log(data) { 
    console.log(JSON.stringify(data,undefined,2)) 
} 

(async function() { 

    try { 

    const conn = await mongoose.connect(uri,options); 

    // Clean data 
    await Promise.all(
     Object.keys(conn.models).map(m => conn.models[m].remove({})) 
    ); 

    // Create a document 
    let test = await Test.create({ 
     name: 'john doe', 
     phone: '+12345678901' 
    }); 
    log(test); 

    // This update will apply using $set for the name 
    let notover = await Test.findOneAndUpdate(
     { _id: test._id }, 
     { name: 'Bill S. Preston' }, 
     { new: true } 
    ); 
    log(notover); 

    // This update will just use the supplied object, and overwrite 
    let updated = await Test.findOneAndUpdate(
     { _id: test._id }, 
     { name: 'Dan Smith' }, 
     { new: true, overwrite: true } 
    ); 
    log(updated); 


    } catch (e) { 
    console.error(e); 
    } finally { 
    mongoose.disconnect(); 
    } 

})() 

が生成されます:

フル例として

:あなたが実際にこのような場合にはそれを行うにはしたくないので、あなたはどの.update()メソッドに渡されるオプションに{ overwrite: true }を経由してその動作をオフにします

Mongoose: tests.remove({}, {}) 
Mongoose: tests.insert({ name: 'john doe', phone: '+12345678901', _id: ObjectId("596efb0ec941ff0ec319ac1e"), __v: 0 }) 
{ 
    "__v": 0, 
    "name": "john doe", 
    "phone": "+12345678901", 
    "_id": "596efb0ec941ff0ec319ac1e" 
} 
Mongoose: tests.findAndModify({ _id: ObjectId("596efb0ec941ff0ec319ac1e") }, [], { '$set': { name: 'Bill S. Preston' } }, { new: true, upsert: false, remove: false, fields: {} }) 
{ 
    "_id": "596efb0ec941ff0ec319ac1e", 
    "name": "Bill S. Preston", 
    "phone": "+12345678901", 
    "__v": 0 
} 
Mongoose: tests.findAndModify({ _id: ObjectId("596efb0ec941ff0ec319ac1e") }, [], { name: 'Dan Smith' }, { new: true, overwrite: true, upsert: false, remove: false, fields: {} }) 
{ 
    "_id": "596efb0ec941ff0ec319ac1e", 
    "name": "Dan Smith" 
} 

これ以外の場合は補間されていた$setの操作が抑制されているため、ドキュメントが上書きされています。 2つのサンプルは$set修飾子を適用したoverwriteオプションを使用しないで最初に表示され、overwriteオプションを使用すると、 "更新"のために渡したオブジェクトが尊重され、そのような$set修飾子は適用されません。

MongoDBノードドライバがこれを「デフォルトで」行う方法です。だから、暗黙のうちに "$set"を追加する振る舞いは、あなたが言っていない限り、mongooseによって行われています。

+0

ありがとう、この上書き機能は完全に文書化されていません:-( –

0

あなたはupsertオプションを渡すことができ、それが文書に置き換えられます:ここ

var collection = db.collection('test'); 
collection.findOneAndUpdate(
    {'_id': 'some_mongodb_id'}, 
    {name: 'Dan smith Only'}, 
    {upsert: true}, 
    function (err, doc) { 
    console.log(doc); 
    } 
); 

しかし、問題は - コールバックでdocは、文書が見つかりましたが、更新されていないということです。

var collection = db.collection('test'); 
collection.update(
    {'_id': 'some_mongodb_id'}, 
    {name: 'Dan smith Only'}, 
    {upsert: true}, 
    function (err, doc) { 
    collection.findOne({'_id': 'some_mongodb_id'}, function (err, doc) { 
     console.log(doc); 
    }); 
    } 
);