使用findOneAndUpdate $拉和填充不会更新或填充
这是我的数据:
{ "_id" : ObjectId("594e762b03cc52508686ceef"), "_members" : [ "59527bd5e521801bf07eab98", "594ecca47a699d1775c2a2db" ], }
我想从_members
删除_members
。
PostSchema:
const PostsSchema = new Schema({ // ... _members: [{ type: Schema.Types.ObjectId, ref: 'user' }], // ... })
UserSchema:
const UserSchema = new Schema({ // ... posts : [{ type: Schema.Types.ObjectId, ref: 'post' }], // ... })
查找和更新:
let id = mongoose.mongo.ObjectID(req.params.id) let member = mongoose.mongo.ObjectID(req.params.member) let populateQuery = [ {path:'_members', select:'_id'} ] Post. findOneAndUpdate( {'_id' : id} , { $pull: { '_members': { '_id': member }} }, {'new': true} ). populate(populateQuery). exec( function (err, data) { res.send(data) } );
有趣的是,“人口”似乎只能通过在这种情况下将model
选项指定为.populate()
来工作。
你也只需要提供member
直接$pull
因为_id
实际上不是一个属性,直到“填充”。 "_members"
数组只是Post
本身内的一个ObjectId
值的数组。 所以直接提供input:
Post.findOneAndUpdate( {'_id' : id} , { $pull: { '_members': member } }, {'new': true} ) .populate({path:'_members', select:'_id', model: 'user' }) .exec(function(err,post) { if (err) throw err; // or something res.send(post) })
或与承诺
Post.findOneAndUpdate( {'_id' : id} , { $pull: { '_members': member } }, {'new': true} ) .populate({path:'_members', select:'_id', model: 'user' }) .then(post => res.send(post)) .catch(err => console.error(err)); // or something
或者调用Model.populate()
来代替:
Post.findOneAndUpdate( {'_id' : id} , { $pull: { '_members': member } }, {'new': true} ).exec(function(err,post) { if (err) throw err; // or something Post.populate(post, {path:'_members', select:'_id', model: 'user' },function(err,post) { if (err) throw err; // or something res.send(post); // now populated } })
或者交替使用Promise:
Post.findOneAndUpdate( {'_id' : id} , { $pull: { '_members': member } }, {'new': true} ) .then(post => Post.populate(post, {path:'_members', select:'_id', model: 'user' })) .then(post => res.send(post)) // also populated .catch(err => console.error(err)) // or whichever
当你只是要求返回已经embedded到文档中的_id
字段时,为什么要调用.populate()
有些不确定,但这是另一种情况。 在model
选项中,人口实际上是在这里发生的。
作为一个独立的示范:
const async = require('async'), mongoose = require('mongoose'), Schema = mongoose.Schema; mongoose.Promise = global.Promise; mongoose.set('debug',true); mongoose.connect('mongodb://localhost/test'); const relSchema = new Schema({ c: String }); const testSchema = new Schema({ a: String, b: [{ type: Schema.Types.ObjectId, rel: 'Rel' }] }) const Test = mongoose.model('Test', testSchema); const Rel = mongoose.model('Rel', relSchema); function log(data) { console.log(JSON.stringify(data, undefined, 2)) } async.series( [ (callback) => async.each(mongoose.models,(model,callback) => model.remove({},callback),callback), (callback) => async.waterfall( [ (callback) => Rel.create([{ c: 2 },{ c: 3 },{ c: 4 }],callback), (rels,callback) => Test.create({ a: 1, b: rels },(err,test) => { if (err) callback(err); log(test); callback(err,test.b.slice(1,3)) }), (rels,calback) => Test.findOneAndUpdate( { 'a': 1 }, { '$pull': { 'b': rels[0] } }, { 'new': true } ) .populate({ path: 'b', model: 'Rel' }) .exec((err,test) => { if (err) callback(err); log(test); callback(err); }) ], callback ) ], (err) => { if (err) throw err; mongoose.disconnect(); } )
而输出:
Mongoose: tests.remove({}, {}) Mongoose: rels.remove({}, {}) Mongoose: rels.insert({ c: '2', _id: ObjectId("595714579afd8860e56d2ec7"), __v: 0 }) Mongoose: rels.insert({ c: '3', _id: ObjectId("595714579afd8860e56d2ec8"), __v: 0 }) Mongoose: rels.insert({ c: '4', _id: ObjectId("595714579afd8860e56d2ec9"), __v: 0 }) Mongoose: tests.insert({ a: '1', _id: ObjectId("595714579afd8860e56d2eca"), b: [ ObjectId("595714579afd8860e56d2ec7"), ObjectId("595714579afd8860e56d2ec8"), ObjectId("595714579afd8860e56d2ec9") ], __v: 0 }) { "__v": 0, "a": "1", "_id": "595714579afd8860e56d2eca", "b": [ "595714579afd8860e56d2ec7", "595714579afd8860e56d2ec8", "595714579afd8860e56d2ec9" ] } Mongoose: tests.findAndModify({ a: '1' }, [], { '$pull': { b: ObjectId("595714579afd8860e56d2ec8") } }, { new: true, upsert: false, remove: false, fields: {} }) Mongoose: rels.find({ _id: { '$in': [ ObjectId("595714579afd8860e56d2ec7"), ObjectId("595714579afd8860e56d2ec9") ] } }, { fields: {} }) { "_id": "595714579afd8860e56d2eca", "a": "1", "__v": 0, "b": [ { "_id": "595714579afd8860e56d2ec7", "c": "2", "__v": 0 }, { "_id": "595714579afd8860e56d2ec9", "c": "4", "__v": 0 } ] }