node.js 保存后猫鼬填充
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13525480/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Mongoose populate after save
提问by Pykler
I cannot manually or automatically populate the creator field on a newly saved object ... the only way I can find is to re-query for the objects I already have which I would hate to do.
我无法在新保存的对象上手动或自动填充创建者字段......我能找到的唯一方法是重新查询我已经拥有的对象,而我不想这样做。
This is the setup:
这是设置:
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);
This is where I am pulling my hair
这是我拉头发的地方
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?
});
});
EDIT: latest mongoose fixed this issue and added populate functionality, see the new accepted answer.
编辑:最新的猫鼬修复了这个问题并添加了填充功能,请参阅新接受的答案。
回答by user1417684
You should be able to use the Model's populate function to do this: http://mongoosejs.com/docs/api.html#model_Model.populateIn the save handler for book, instead of:
您应该能够使用模型的 populate 函数来执行此操作:http: //mongoosejs.com/docs/api.html#model_Model.populate在 book 的保存处理程序中,而不是:
book._creator = user;
you'd do something like:
你会做这样的事情:
Book.populate(book, {path:"_creator"}, function(err, book) { ... });
Probably too late an answer to help you, but I was stuck on this recently, and it might be useful for others.
可能为时已晚,无法为您提供帮助,但我最近陷入了困境,这可能对其他人有用。
回答by Eric Saboia
In case that anyone is still looking for this.
如果有人仍在寻找这个。
Mongoose 3.6 has introduced a lot of cool features to populate:
Mongoose 3.6 引入了很多很酷的特性来填充:
book.populate('_creator', function(err) {
console.log(book._creator);
});
or:
或者:
Book.populate(book, '_creator', function(err) {
console.log(book._creator);
});
see more at: https://github.com/LearnBoost/mongoose/wiki/3.6-Release-Notes#population
查看更多:https: //github.com/LearnBoost/mongoose/wiki/3.6-Release-Notes#population
But this way you would still query for the user again.
但是这样你仍然会再次查询用户。
A little trick to accomplish it without extra queries would be:
在没有额外查询的情况下完成它的一个小技巧是:
book = book.toObject();
book._creator = user;
回答by Fran?ois Romain
The solution for me was to use execPopulate, like so
我的解决方案是使用execPopulate,像这样
const t = new MyModel(value)
return t.save().then(t => t.populate('my-path').execPopulate())
回答by Govind Rai
Solution which returns a promise (no callbacks):
返回承诺的解决方案(无回调):
Use Document#populate
使用文档#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 => {
...
});
Read about document population here.
回答by Pratik Bothra
Just to elaborate and give another example, as it helped me out. This might help those who want to to retrieve partially populated objects after save. The method is slightly different as well. Spent more than an hour or two looking for the correct way to do it.
只是为了详细说明并举另一个例子,因为它帮助了我。这可能有助于那些想要在保存后检索部分填充对象的人。方法也略有不同。花了一两个多小时寻找正确的方法。
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);
});
});
回答by curzmg
I thought I'd add to this to clarify things for complete noobs like myself.
我想我会添加这个来澄清像我这样的完全菜鸟的事情。
What's massively confusing if you're not careful is that there are three very different populate methods. They are methods of different objects (Model vs. Document), take different inputs and give different outputs (Document vs. Promise).
如果您不小心,最令人困惑的是存在三种截然不同的填充方法。它们是不同对象的方法(模型与文档),采用不同的输入并给出不同的输出(文档与承诺)。
Here they are for those that are baffled:
他们是为那些感到困惑的人准备的:
Document.prototype.populate()
Document.prototype.populate()
This one works on documents and returns a document. In the original example, it would look like this:
这个适用于文档并返回一个文档。在原始示例中,它看起来像这样:
book.save(function(err, book) {
book.populate('_creator', function(err, book) {
// Do something
})
});
Because it works on documents and returns a document, you can chain them together like so:
因为它适用于文档并返回一个文档,所以您可以像这样将它们链接在一起:
book.save(function(err, book) {
book
.populate('_creator')
.populate('/* Some other ObjectID field */', function(err, book) {
// Do something
})
});
But don't be silly, like me, and try to do this:
但是不要像我一样傻,尝试这样做:
book.save(function(err, book) {
book
.populate('_creator')
.populate('/* Some other ObjectID field */')
.then(function(book) {
// Do something
})
});
Remember: Document.prototype.populate() returns a document, so this is nonsense. If you want a promise, you need...
记住:Document.prototype.populate() 返回一个文档,所以这是无稽之谈。如果你想要一个承诺,你需要...
Document.prototype.execPopulate()
Document.prototype.execPopulate()
This one works on documents BUT it returns a promise that resolves to the document. In other words, you can use it like this:
这个适用于文档,但它返回一个解析为文档的承诺。换句话说,您可以像这样使用它:
book.save(function(err, book) {
book
.populate('_creator')
.populate('/* Some other ObjectID field */')
.execPopulate()
.then(function(book) {
// Do something
})
});
That's better. Finally, there's...
这样更好。最后,有...
Model.populate()
模型.populate()
This one works on modelsand returns a promise. It's therefore used a bit differently:
这个适用于模型并返回一个承诺。因此它的使用方式有点不同:
book.save(function(err, book) {
Book // Book not book
.populate(book, { path: '_creator'})
.then(function(book) {
// Do something
})
});
Hope that's helped some other newcomers.
希望这对其他一些新人有所帮助。
回答by Whisher
Mongoose 5.2.7
猫鼬 5.2.7
This works for me (just a lot of headache !)
这对我有用(只是很头疼!)
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);
});
};
回答by freakish
Unfortunetly this is a long standing issue with mongoose which I believe is not solved yet:
不幸的是,这是猫鼬的一个长期存在的问题,我认为尚未解决:
https://github.com/LearnBoost/mongoose/issues/570
https://github.com/LearnBoost/mongoose/issues/570
What you can do is to write you own custom getter/setter ( and set real_customerin a seperate property ) for this. For example:
您可以做的是为此编写自己的自定义 getter/setter(并在单独的属性中设置real_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:I didn't test it and it might work strangely with .populateand when setting pure id.
注意:我没有测试它.populate,当设置纯 id 时它可能会奇怪地工作。
回答by WouldBeNerd
ended up writing some curry-able Promise functions where you declare your schema, query_adapter, data_adapter functions and populate string in advance. For a shorter / simpler implementation easier on.
最终编写了一些可使用咖喱的 Promise 函数,您可以在其中声明架构、query_adapter、data_adapter 函数并提前填充字符串。对于更短/更简单的实现更容易。
It's probably not super efficient, but I thought the execution bit was quite elegant.
它可能不是非常高效,但我认为执行位非常优雅。
github file: curry_Promises.js
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 )
回答by kboom
Probably sth. like
大概…… 喜欢
Book.createAsync(bookToSave).then((savedBook) => savedBook.populateAsync("creator"));
Would be the nicest and least problematic way to make this work (Using Bluebird promises).
将是完成这项工作的最好且问题最少的方法(使用 Bluebird 承诺)。

