Bug? mongoose不能更新嵌入的数组中的值?
发布于 11 年前 作者 jbasttdi 10965 次浏览 最后一次编辑是 8 年前

大家好,不知为什么mongoose不能更新嵌入的数组中的数据。 ’’' var MySchema=new Schema({ id:ObjectId, msgbody:String, replymsg:[ReplyPerson] });

var ReplyPerson=new Schema({ rid:ObjectId, parentid:ObjectId, rmsg:String, rimgurls:[String], });

传调参数示例: params:{schemaid:1,childid:2};

就是MySchema中的replymsg数组中找rid为2的记录,并把其中的rmsg改为’cccccccc’

exports.myupdate = function (params, data, callback) { MySchema.findOne({_id:params.schemaid}, function (err, mySchema) { if (err) { console.log(‘Err:’ + err); return callback(err); } if (!mySchema) { return callback(new Error(‘无可更新内容!’)); } //如果直接这样赋值是可以改变的。 mySchema.replymsg=[‘aaaa’,‘bbbb’]; for(var key in mySchema.replymsg){ // console.log(‘key:’+key); var obj=mySchema.replymsg[key]; // console.log(‘obj:’+obj); if(obj.parentid==params.schemaid && obj.rid=params.childid){ //通过调试,这是是会执行到的,但最终mongodb 中值还是原来的值。 mySchema.replymsg[key].rmsg=‘cccccccccccccc’; break; } } mySchema.save(callback); }); }; ’’' 但当我执行这段代码后,mongodb中记录一直没改变。 可如果我不是通过改变数组中的记录内容,直接把整个数组赋值mySchema.replymsg=[‘aaaa’,‘bbbb’];是会改变值的。 难道mongoose不能自动检测到数组中的值已经变化过,如果是这样,那么有没有什么值可以手动设置让mongoose知道这些值变化了呢? 非常感谢! 调了一个上午,始终不行,求救!!!

6 回复

首先MySchema.findById(params.schemaid,function(err,reply){

如果reply有值, 那么reply.replymsg就是子文档的值 通过一个子文档查询的方法:var hasId = reply.replymsg.id(params.childid); 如果这个hasId为真。那就是在子文档中查到了这个childid 如果要update子文档。 目前只有一种办法 就是: if(hasId){ hasId.remove(); //或者reply.replymsg.pull({rid: params.childid}); } 然后再执行reply.replymsg.addToSet(新的对象是由原来的rid和其它不改变的值以及,新的update的值组成);

这个新的对象,也可以在前面把它查出来,把查到的值给这个新的对象,同时把要改变的比如:子文档中的rmsg设定为 你要update的值

});

感谢sogego的回复,我又仔细看了一遍官网和FAQ,现终于有点明白,做了个示例,供讨论。 <a href=“http://mongoosejs.com/docs/faq.html” target="_blank">官方FAQ文档</a>

Model文件 DParent.js <code> var mongoose=require(‘mongoose’); var Schema=mongoose.Schema; var ObjectId = Schema.ObjectId; var DChild=require(’./DChild’);

var DParentSchema=new Schema({ msgbody:String, childs:[DChild.DChildSchema] });

mongoose.model(‘DParent’,DParentSchema); </code>

DChild.js <code> var mongoose=require(‘mongoose’); var Schema=mongoose.Schema; var ObjectId = Schema.ObjectId;

var DChildSchema=new Schema({ parentid:ObjectId, childmsg:String, substrings:[String] });

exports.DChildSchema=DChildSchema; mongoose.model(‘DChild’,DChildSchema); </code>

DUpdate.js <code> var models = require(’…/models’); var DParent = models.DParent; var DChild = models.DChild; exports.updateaction = function (req, res,next) { // var dp=new DParent(); // dp.msgbody=‘parent msg1’; // var dchild0=new DChild(); // dchild0.parentid=dp._id; // dchild0.childmsg=‘children msg’; // dchild0.substrings.push(‘str1’); // dchild0.substrings.push(‘str2’); // dchild0.substrings.push(‘str3’); // dp.childs.push(dchild0); // dp.save(function(err,result){ // res.send(’’); // return next(); // }); DParent.findOne({_id:‘52e526f36dbf1d94255e39a8’}, function (err, dparent) { if (err) { console.log(‘Err:’ + err); } if (!dparent) { console.log(‘no document’); } dchild0=dparent.childs[0]; dchild0.childmsg=‘from parent’; //对于不是数组类型的字段直接通过这种方法来修改 // dchild0.substrings.splice(0,1); //在子文档child0的substrings这个数组中删除第一个记录 //dchild0.substrings.push(‘push22’); //在子文档child0的substrings这个数组中增加一个记录 //这种方式不行 dchild0.substrings[0]=‘up0000’; //这种方法不能够修改数组中的值。。。。。。 dchild0.substrings.set(0,‘updated by parent1’); //如要修改数组中的值,需用这个set方法,"0"表示要修改substrings数据的第1条记录 dparent.save(function(err,result){ if(err){ console.log(‘save error!’); } console.log(result); res.send(’’); return next(); }); }); }; </code>

调用方法: var dts=require(’./action/DUpdate’); server.get(’/api_v1/ts’,dts.updateaction);

数据库结构:

{ "__v" : 10, "_id" : ObjectId(“52e526f36dbf1d94255e39a8”), “childs” : [{ "_id" : ObjectId(“52e526f36dbf1d94255e39a9”), “childmsg” : “from parent”, “parentid” : ObjectId(“52e526f36dbf1d94255e39a8”), “substrings” : [“updated by parent1”, “sub1”, “sub2”, “sub3”] }], “msgbody” : “parent msg1” }

还有忘记说一点,定义父类的Schema时,数组中的子类也要是子类的Schema,不能是子类的Model var DParentSchema=new Schema({ msgbody:String, childs:[DChild.DChildSchema] //不能定义成 childs:[DChild] ,这里DChild是Model,虽然大多数情况没问题,但遇到要更改数组中的值就不行了。 });

此坑我也遇到过,在执行这句mySchema.save(callback);之前加一句mySchema.markModified('replymsg')

http://cnodejs.org/topic/516ab9c96d38277306376cad

这个要马克~

回到顶部