【问题标题】:Saving populated values in Mongoose在 Mongoose 中保存填充值
【发布时间】:2017-09-23 00:04:06
【问题描述】:

如果我在将文档发送到客户端之前获取并填充它,那么在进行更新时取消填充这些字段的最佳方法是什么?

模式:

var User = new mongoose.Schema({
  name: String
});

var Post = new mongoose.Schema({
  title: String,
  likes: [{
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User'
  }]
});

控制器:

app.get('/post/:id', function (req, res, next) {
  Post.findById(req.params.id).populate('likes').exec(function (err, post) {
    if (err) return next(err);
    res.json(post);
  });
});

app.put('/post/:id', function (req, res, next) {
  Post.findById(req.params.id, function (err, post) {
    if (err) return next(err);

    _.extend(post, req.body);
    post.save(function (err) {
      if (err) return next(err);
      res.json(post);
    });
  });
});

所以在客户端我收到类似的东西:

{
  _id: 123,
  title: 'Test post',
  likes: [{
    _id: 456,
    name: 'John Doe'
  }, {
    _id: 789,
    name: 'Max Danger'
  }]
}

这一切都很好。但是当我在客户端修改模型(我使用Backbone.Marionette FWIW),然后将其保存回来时,Mongoose 会抛出Cast to ObjectId failed for value "[object Object],456" at path "likes" 错误。

我认为 Mongoose 能够自动从这些对象中抓取 _ids,但它似乎不是那样工作的......?

那么这里最好的方法是什么?在发送到服务器之前,我应该在客户端上提取 ID 吗?还是我在调用 save 之前先在服务器上拔?

另外,保存后我需要重新填充这些字段,然后再将保存的产品再次发送回客户,对吗?

最后,我认为我不能实际上使用 Mongoose 的 depopulate() 方法,因为我只有从客户端接收到的 JSON,而不是实际的 Model 实例。

任何帮助..?谢谢!

【问题讨论】:

  • 您可以使用Mongoose' middleware 在保存文档之前从 JSON 中删除这些属性,schema.pre('save', function (next) {...}) 否则如果添加到客户端上的数组仅在更新时发送 id 数组
  • 谢谢,我想我曾经尝试过,而且我认为它有效。我想我只是希望我错过了 Mongoose 中会自动获取 ID 的东西。另外,使用预保存钩子不适用于实例化新模型,这有时也是我的情况。这意味着客户端将完整的对象发送到 POST 处理程序,并且 POST 处理程序使用new Model(req.body) 进行实例化。如果我不先提取 ID,它会在实例化时失败。所以也许客户端采摘对这两种情况都是最有意义的。谢谢。

标签: node.js backbone.js express mongoose marionette


【解决方案1】:

你可以使用node的下划线库代替mongoose的depopulate()方法,它提供了一个函数pick,并返回给定对象的选择值并更快地计算结果here is example

app.get('/post/:id', function (req, res, next) {

Post.findById(req.params.id).populate('likes').exec(function (err, post) {

if (err) return next(err);

 var depopulate  = _.pick(post, '_id');

 res.json(depopulate);

});
});

depopulate 变量将存储来自结果查询文档的_id's 您可以轻松地将所有_id's 发送给客户。

【讨论】:

  • 我的问题不在于我发送给客户的时候。事实上,我想要将填充的文档发送给客户端。问题是在客户端中进行更改然后将其发布回来。那时我需要减少人口。但是您的示例仍然相关,实际上我在保存回数据库之前正在使用_.pick()。我只是想知道是否有我忽略的东西,因为我实际上有几个填充字段(数组和单个对象),所以在整个地方进行这种“人口减少”很麻烦。 :-/
【解决方案2】:

我知道这个问题是 2 年前发布的,但我认为它可能会对您有所帮助.. 您可以重写一些预定义的方法来完成您需要的工作。

UserSchema.methods.toJSON = function () {

    var user = this.toObject();  
    return _.pick(user, ['_id', 'email']);

};

就像我重写了 toJSON 方法只发送 _id 和电子邮件,而不是发送整个用户文档。

【讨论】:

    猜你喜欢
    • 2023-03-14
    • 2021-11-17
    • 2016-07-11
    • 2019-07-28
    • 2014-06-19
    • 2012-01-22
    • 2013-02-03
    • 2019-03-28
    • 1970-01-01
    相关资源
    最近更新 更多