Chaining promise to update a reference document in

2019-05-30 06:30发布

问题:

Given the following schema:

user
  { uid:12345, name:myname, account=null }

account
  { _id:6789, name:"myaccount", _owner:12345 }

How can I update the user.account to have the value of its referenced field account._owner. When the account document is created I want to find and replace the user.account value. The route I have looks like this:

app.post('/accounts', authenticate, (req, res) => {
    var account = new Account({
        name: req.body.name,
        _owner: req.body._owner,
    });
    account.save().then((doc) => {
    //here i wasnt to update a refernce to a 
    // an account field in a User document and set 
    //it to the account.owner created above.
        res.send(doc);
    }, (e) => {
        res.status(400).send(e);
    });
});

In my example when the account is created I want to update user.account to 6789 (the value of the created account id)

回答1:

Mongoose handles promises : http://mongoosejs.com/docs/promises.html

So you can simply :

app.post('/accounts', authenticate, (req, res) => {
    var account = new Account({
        name: req.body.name,
        _owner: req.body._owner,
    });
    account.save()
        .then((doc) => User.findOneAndUpdate(
            { uid: req.body._owner },
            { $set: { account: doc._id } },
            { new: true }
        )
        .then(() => doc);
    }).then((account) => {
        res.send(account);
    }, (e) => {
        res.status(400).send(e);
    });
});


回答2:

Another solution would be to attach a hook to the save action of account model

var Owner = require('path/to/owner/model');
var schema = new Schema({name:String,_owner:{type: Schema.Types.ObjectId,ref: 'owner'}}); // ref will be useful if you want to use populate later
schema.post('save', function(account) {
  return Owner.findOne({uid:account._owner})
      .then(owner => {
        owner.account = account._id; // assign account id to user
        return owner.save();
      })
});

Then you just have to create a new account object and the hook will do it in the background.

app.post('/accounts', authenticate, (req, res) => {
var account = new Account({
    name: req.body.name,
    _owner: req.body._owner,
});
account.save().then((doc) => {
    res.send(doc);
}, (e) => {
    res.status(400).send(e);
});
});

IMO, the routes look cleaner this way, you could try it out.