猫鼬被拯救后开始繁殖

我不能手动或自动填充一个新保存的对象的创建者字段... 唯一的方法,我可以找到是重新查询对象,我已经有,我讨厌这样做。

这是设置:

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?
});
});

编辑: 最新的猫鼬修复了这个问题,并添加了填充功能,见新的接受的答案。

82932 次浏览

不幸的是,这是猫鼬的一个长期问题,我相信这个问题还没有解决:

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,
});

注意: 我没有测试它,它可能在 .populate和设置纯 id 时工作得很奇怪。

你应该能够使用模型的填充函数来做到这一点: http://mongoosejs.com/docs/api.html#model_Model.populate在图书的保存处理程序中,而不是:

book._creator = user;

你会这样做:

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.

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);
});
});

以防有人还在找这个。

Mongoose 3.6 has introduced a lot of cool features to populate:

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

或:

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

see more at: https://github.com/LearnBoost/mongoose/wiki/3.6-Release-Notes#population

但是通过这种方式,您仍然可以再次查询用户。

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

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

可能是... ... 之类的

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

将是实现这一目标的最好和问题最少的方法(使用 Bluebird 承诺)。

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

使用文档 # 填充

book.populate('creator').execPopulate();


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

可能推行的措施

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

阅读有关文档填充 给你

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

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

我觉得我应该加点东西给像我这样的菜鸟澄清一下。

如果您不小心的话,最令人困惑的是有三种非常不同的填充方法。它们是不同对象的方法(模型与文档) ,接受不同的输入并提供不同的输出(文档与承诺)。

以下是给那些感到困惑的人的建议:

()

看完整的文件。

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
})
});

因为它可以处理文档并返回文档,所以您可以像下面这样将它们链接在一起:

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 ()返回一个文档,所以这是没有意义的。

ExecPopular ()

看完整的文件。

这一个工作在文档上,但它返回一个承诺,解决文档。 换句话说,你可以这样使用它:

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

好多了,终于..。

使用 Model.popular ()

看完整的文件。

这个 在模特身上工作返回一个承诺,因此它的用法有点不同:

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

希望这对其他新人有所帮助。

猫鼬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);
});
};

最后编写了一些可以用咖喱表示的瓶颈函数,在这些函数中,需要预先声明模式、 query _ Adapter、 data _ Adapter 函数并填充字符串。对于更短/更简单的实现更容易。

It's probably not super efficient, but I thought the execution bit was quite elegant.

github file: 咖喱承诺

声明

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}
})

处决

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

在模型中保存文档,然后填充

   chatRoom = await chatRoom.save();
const data = await chatRoom
.populate("customer", "email dp")
.populate({
path: "admin",
select: "name logo",
})
.execPopulate();

我不会添加任何新的内容。

这只是一种更简洁的使用异步/等待来编写代码的方法:

const newCourse = new Course(new_course_data);
const populate_options = [
// Here write your populate options
];
const created_course = await newCourse.save();
await created_course.populate(populate_options).execPopulate();

这招对我很管用

    let post = await PostModel.create({
...req.body, author: userId
})


post = await post.populate('author', 'name')


res.status(200).json({
status: 'success',
data: { post }
})

在 Mongoose 6.x 中,你只需要做:

const t = await MyModel.create(value).then((t) =>
t.populate('my-path')
);

execPopulate()方法现在已被删除。

我没有工作,所以我保存,然后使用 findById 得到的数据与填充回来

const data: any = await Model.findById(id)
.populate("name")
  

我使用 异步/等待时使用 popular 的方法是:

const updatedBook = await book.save()
const populatedBook = await updatedBook.populate('field', { name: 1, author: 1, field3: 1})

其中 fieldName: 1告诉从“字段”填充哪些字段。

如果是 我保证的话,可能会像这样:

book.save()
.then(savedBook => savedBook.populate())
.then(populatedBook => populatedBook)