说,我有一份文件:
{ _id: 'some_mongodb_id',name: 'john doe',phone: '+12345678901',}
我想更新这个文件:
.findOneAndUpdate({_id: 'some_mongodb_id'},{name: 'Dan smith'})
结果应该是这样的:
{ _id: 'some_mongodb_id',name: 'Dan smith',}
我怎么做?
解决方法
实际上,但是由于mongoose实际上“搞乱”了更新,这实际上是你提交给常规MongoDB函数的默认操作.
因此,mongoose认为它“明智”是一种“假设”你想要在这里发出$set
指令的便利方法.由于在这种情况下您实际上不想这样做,因此在传递给任何.update()方法的选项中通过{overwrite:true}关闭该行为:
作为一个完整的例子:
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(); } })()
生产:
Mongoose: tests.remove({},{}) Mongoose: tests.insert({ name: 'john doe',_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' } },upsert: false,remove: false,fields: {} }) { "_id": "596efb0ec941ff0ec319ac1e","name": "Bill S. Preston","__v": 0 } Mongoose: tests.findAndModify({ _id: ObjectId("596efb0ec941ff0ec319ac1e") },overwrite: true,"name": "Dan Smith" }
显示文档被“覆盖”,因为我们抑制了$set
操作,否则将被插值.这两个样本首先显示没有覆盖选项,后者应用$set
修饰符,然后“使用”覆盖选项,其中传递了为“更新”传递的对象,并且不应用此类$set
修饰符.
注意,这是MongoDB节点驱动程序“默认”执行此操作的方式.因此,添加“隐式”$set
的行为是由猫鼬完成的,除非你告诉它不要.