首页 文章

保存后,猫鼬会填充

提问于
浏览
69

我不能手动或自动填充新保存的对象上的创建者字段...我能找到的唯一方法是重新查询我已经拥有的我不想做的对象 .

这是设置:

var userSchema = new mongoose.Schema({   
  name: String,
});
var User = db.model('User', userSchema);

var bookSchema = new mongoose.Schema({
  _creator: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
  description: String,
});
var Book = db.model('Book', bookSchema);

这是我拉我的头发的地方

var user = new User();
user.save(function(err) {
    var book = new Book({
        _creator: user,
    });
    book.save(function(err){
        console.log(book._creator); // is just an object id
        book._creator = user; // still only attaches the object id due to Mongoose magic
        console.log(book._creator); // Again: is just an object id
        // I really want book._creator to be a user without having to go back to the db ... any suggestions?
    });
});

编辑:最新的mongoose解决了这个问题并添加了填充功能,请参阅新接受的答案 .

10 回答

  • 0

    您应该能够使用Model的populate函数来执行此操作:http://mongoosejs.com/docs/api.html#model_Model.populate在book的保存处理程序中,而不是:

    book._creator = user;
    

    你会做类似的事情:

    Book.populate(book, {path:"_creator"}, function(err, book) { ... });
    

    可能来得太晚了,无法帮助你,但最近我被困在这个问题上,对其他人来说可能有用 .

  • 119

    如果有人还在寻找这个 .

    Mongoose 3.6引入了许多很酷的功能来填充:

    book.populate('_creator', function(err) {
     console.log(book._creator);
    });
    

    要么:

    Book.populate(book, '_creator', function(err) {
     console.log(book._creator);
    });
    

    更多信息见:https://github.com/LearnBoost/mongoose/wiki/3.6-Release-Notes#population

    但是这样你仍然会再次查询用户 .

    在没有额外查询的情况下完成它的一个小技巧是:

    book = book.toObject();
    book._creator = user;
    
  • 11

    只是为了详细说明并给出另一个例子,因为它帮助了我 . 这可能有助于那些想要在保存后检索部分填充对象的人 . 该方法也略有不同 . 花了一两个多小时寻找正确的方法 .

    post.save(function(err) {
        if (err) {
          return res.json(500, {
            error: 'Cannot save the post'
          });
        }
        post.populate('group', 'name').populate({
          path: 'wallUser',
          select: 'name picture'
        }, function(err, doc) {
          res.json(doc);
        });
      });
    
  • 8

    返回promise的解决方案(无回调):

    Use Document#populate

    book.populate('creator').execPopulate();
    
    // summary
    doc.populate(options);               // not executed
    doc.populate(options).execPopulate() // executed, returns promise
    

    Possible Implementation

    var populatedDoc = doc.populate(options).execPopulate();
    var populatedDoc.then(doc => {
       ... 
    });
    

    阅读有关文档填充here的信息 .

  • 34

    我的解决方案是使用 execPopulate ,就像这样

    const t = new MyModel(value)
    return t.save().then(t => t.populate('my-path').execPopulate())
    
  • 10

    我想我会加上这个来澄清像我这样的完整新手的东西 .

    如果你不小心,有什么令人困惑的是,有三种截然不同的填充方法 . 它们是不同对象的方法(模型与文档),采用不同的输入并给出不同的输出(Document vs. Promise) .

    在这里,他们是那些困惑的人:

    Document.prototype.populate()

    See full docs.

    这个适用于文档并返回文档 . 在原始示例中,它看起来像这样:

    book.save(function(err, book) {
        book.populate('_creator', function(err, book) {
            // Do something
        })
    });
    

    因为它适用于文档并返回文档,所以您可以将它们链接在一起,如下所示:

    book.save(function(err, book) {
        book
        .populate('_creator')
        .populate('/* Some other ObjectID field */', function(err, book) {
            // Do something
        })
    });
    

    但是,不要像我一样愚蠢,并尝试这样做:

    book.save(function(err, book) {
        book
        .populate('_creator')
        .populate('/* Some other ObjectID field */')
        .then(function(book) {
            // Do something
        })
    });
    

    请记住:Document.prototype.populate()返回一个文档,所以这是无稽之谈 . 如果你想要一个承诺,你需要......

    Document.prototype.execPopulate()

    See full docs.

    这个适用于文档,但它返回一个解析为文档的promise . 换句话说,您可以像这样使用它:

    book.save(function(err, book) {
        book
        .populate('_creator')
        .populate('/* Some other ObjectID field */')
        .execPopulate()
        .then(function(book) {
            // Do something
        })
    });
    

    那更好 . 最后,还有......

    Model.populate()

    See full docs.

    这个 works on models 并返回一个承诺 . 因此使用方式略有不同:

    book.save(function(err, book) {
        Book // Book not book
        .populate(book, { path: '_creator'})
        .then(function(book) {
            // Do something
        })
    });
    

    希望这能帮助其他一些新人 .

  • 5

    不幸的是,这是一个长期存在的猫鼬问题,我认为还没有解决:

    https://github.com/LearnBoost/mongoose/issues/570

    您可以做的是为此编写自己的自定义getter / setter(并在单独的属性中设置实际 _customer ) . 例如:

    var get_creator = function(val) {
        if (this.hasOwnProperty( "__creator" )) {
            return this.__creator;
        }
        return val;
    };
    var set_creator = function(val) {
        this.__creator = val;
        return val;
    };
    var bookSchema = new mongoose.Schema({
      _creator: {
         type: mongoose.Schema.Types.ObjectId,
         ref: 'User',
         get: get_creator,
         set: set_creator
      },
      description: String,
    });
    

    NOTE: 我没有测试它,它可能与 .populate 奇怪地工作并且设置纯粹的id .

  • 1

    猫鼬5.2.7

    这对我有用(只是很头疼!)

    exports.create = (req, res, next) => {
      const author = req.userData;
      const postInfo = new Post({
        author,
        content: req.body.content,
        isDraft: req.body.isDraft,
        status: req.body.status,
        title: req.body.title
      });
      postInfo.populate('author', '_id email role display_name').execPopulate();
      postInfo.save()
        .then(post => {
          res.status(200).json(post);
        }).catch(error => {
          res.status(500).json(error);
        });
    };
    
  • 0

    可能是某事 . 喜欢

    Book.createAsync(bookToSave).then((savedBook) => savedBook.populateAsync("creator"));
    

    将这项工作作为最好和最不成问题的方法(使用Bluebird承诺) .

  • 1

    最后写了一些curry-able Promise函数,你可以在其中声明你的schema,query_adapter,data_adapter函数并提前填充字符串 . 更简单/更简单的实现更容易 .

    它可能不是超级高效,但我认为执行位非常优雅 .

    github文件:curry_Promises.js

    declartion

    const update_or_insert_Item = mDB.update_or_insert({
        schema : model.Item,
        fn_query_adapter : ({ no })=>{return { no }},
        fn_update_adapter : SQL_to_MDB.item,
        populate : "headgroup"
        // fn_err : (e)=>{return e},
        // fn_res : (o)=>{return o}
    })
    

    execution

    Promise.all( items.map( update_or_insert_Item ) )
    .catch( console.error )
    .then( console.log )
    

相关问题