mongodb Mongoose:深度人口(填充人口稠密的领域)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18867628/
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: deep population (populate a populated field)
提问by f1nn
I have Category
model:
我有Category
型号:
Category:
...
articles: [{type:ObjectId, ref:'Article'}]
Article model contains ref to Account model
.
文章模型包含对 的引用Account model
。
Article:
...
account: {type:ObjectId, ref:'Account'}
So, with populated articles
Category model will be:
因此,使用填充的articles
Category 模型将是:
{ //category
articles: //this field is populated
[ { account: 52386c14fbb3e9ef28000001, // I want this field to be populated
date: Fri Sep 20 2013 00:00:00 GMT+0400 (MSK),
title: 'Article 1' } ],
title: 'Category 1' }
The questions is: how to populate subfield (account) of a populated field ([articles])? Here is how I do it now:
问题是:如何填充已填充字段([文章])的子字段(帐户)?这是我现在的做法:
globals.models.Category
.find
issue : req.params.id
null
sort:
order: 1
.populate("articles") # this populates only article field, article.account is not populated
.exec (err, categories) ->
console.log categories
I know it was discussed here: Mongoose: Populate a populated fieldbut no real solution was found
我知道这里讨论过:猫鼬:填充一个填充的字段,但没有找到真正的解决方案
采纳答案by DestyNova
Mongoose has now a new method Model.populate
for deep associations:
Mongoose 现在有了一种新Model.populate
的深度关联方法:
https://github.com/Automattic/mongoose/issues/1377#issuecomment-15911192
https://github.com/Automattic/mongoose/issues/1377#issuecomment-15911192
回答by techyaura
Firstly, update mongoose 3 to 4 & then use the simplest way for deep population in mongoose as below :
首先,将 mongoose 3 更新为 4,然后使用最简单的方法在 mongoose 中进行深度填充,如下所示:
Suppose you have Blog schema having userId as ref Id & then in User you have some review as ref Id for schema Review. So Basically, you have three schema : 1. Blog 2. User 3. Review
假设您的博客架构将 userId 作为 ref Id,然后在 User 中,您有一些评论作为架构的 ref Id。所以基本上,你有三个架构:1. 博客 2. 用户 3. 评论
And, you have to query from blog, which user owns this blog & the user review. So you can query your result as :
而且,您必须从博客中查询,哪个用户拥有此博客和用户评论。因此,您可以将结果查询为:
BlogModel
.find({})
.populate({
path : 'userId',
populate : {
path : 'reviewId'
}
})
.exec(function (err, res) {
})
回答by Lucas
Populating across multiple levels
跨多个级别填充
Say you have a user schema which keeps track of the user's friends.
假设您有一个用户架构来跟踪用户的朋友。
var userSchema = new Schema({
name: String,
friends: [{ type: ObjectId, ref: 'User' }]
});
Populate lets you get a list of a user's friends, but what if you also wanted a user's friends of friends? Specify the populate option to tell mongoose to populate the friends array of all the user's friends:
Populate 可以让您获得一个用户的朋友列表,但是如果您还想要一个用户的朋友的朋友怎么办?指定 populate 选项来告诉 mongoose 填充所有用户的朋友的朋友数组:
User.findOne({ name: 'Val' }).populate({
path: 'friends',
// Get friends of friends - populate the 'friends' array for every friend
populate: { path: 'friends' }
});
Reference: http://mongoosejs.com/docs/populate.html#deep-populate
回答by Buu Nguyen
It might be a bit too late, but I wrote a Mongoose pluginto perform deep population at any arbitrary nested levels. With this plugin registered, you can populate category's articles and accounts with just a single line:
现在可能有点晚了,但我编写了一个Mongoose 插件来在任意嵌套级别执行深度填充。注册此插件后,您只需一行即可填充类别的文章和帐户:
Category.deepPopulate(categories, 'articles.account', cb)
You can also specify populate optionsto control things like limit
, select
... for each populated path. Checkout the plugin documentation for more information.
您还可以为每个填充的路径指定填充选项来控制诸如limit
, select
... 之类的内容。查看插件文档以获取更多信息。
回答by chovy
Easiest way to accomplish this in 3.6 is to use Model.populate
.
在 3.6 中实现这一点的最简单方法是使用Model.populate
.
User.findById(user.id).select('-salt -hashedPassword').populate('favorites.things').exec(function(err, user){
if ( err ) return res.json(400, err);
Thing.populate(user.favorites.things, {
path: 'creator'
, select: '-salt -hashedPassword'
}, function(err, things){
if ( err ) return res.json(400, err);
user.favorites.things = things;
res.send(user.favorites);
});
});
回答by Ravi Singh
Or you can pass Object to the populate method as:
或者您可以将 Object 传递给 populate 方法:
const myFilterObj = {};
const populateObj = {
path: "parentFileds",
populate: {
path: "childFileds",
select: "childFiledsToSelect"
},
select: "parentFiledsToSelect"
};
Model.find(myFilterObj)
.populate(populateObj).exec((err, data) => console.log(data) );
回答by Kevin Wang
Sorry to burst your bubble, but there's not a directly supported solution to this. As for Github issue #601, it looks grim. According to the 3.6 release notes, it looks like the developers acknowledged the issue are happy with manual recursive/deep population.
很抱歉打破你的泡沫,但没有直接支持的解决方案。至于Github 问题 #601,看起来很严峻。根据3.6 发行说明,看起来开发人员承认该问题对手动递归/深度填充感到满意。
So from the release notes, the recommended method is to nest populated calls in the callback, so in your exec()
function, use categories.populate
to further populate before sending a response.
因此,从发行说明来看,推荐的方法是在回调中嵌套填充的调用,因此在您的exec()
函数中,使用categories.populate
以在发送响应之前进一步填充。
回答by Eat at Joes
globals.models.Category.find()
.where('issue', req.params.id)
.sort('order')
.populate('articles')
.exec(function(err, categories) {
globals.models.Account.populate(categories, 'articles.account', function(err, deepResults){
// deepResult is populated with all three relations
console.log(deepResults[0].articles[0].account);
});
});
The following example is inspired by the question asked @codephobia and populates two levels of many relationships. First fetch a user
, populate its array of related order
s and include each orderDetail
.
以下示例受到@codephobia 提出的问题的启发,并填充了许多关系的两个级别。首先获取 a user
,填充其相关order
s数组并包含每个orderDetail
。
user.model.findOne()
.where('email', '***@****.com')
.populate('orders')
.exec(function(err, user) {
orderDetail.model.populate(user, 'orders.orderDetails', function(err, results){
// results -> user.orders[].orderDetails[]
});
});
This works fine in 3.8.8
but should work in 3.6.x
.
这3.8.8
在3.6.x
.
回答by Shyam Kumar Nallaguntla
This concept is deep Population. Here Calendar,Subscription,User,Apartment are mongoose ODM models in different levels
这个概念是深人口。这里 Calendar,Subscription,User,Apartment 是不同级别的猫鼬 ODM 模型
Calendar.find({}).populate({
path: 'subscription_id',model: 'Subscription',
populate: {path: 'user_id',model: 'User',
populate: {path: 'apartment_id',model: 'Apartment',
populate: {path: 'caterer_nonveg_id',
model: 'Caterer'}}}}).exec(function(err,data){
if(!err){
console.log('data all',data)
}
else{
console.log('err err err',err)
}
});
回答by yyater97
If you want select multi populate inside populate, you should try this way:
如果你想在 populate 中选择multi populate,你应该试试这种方式:
I have Bookingschema:
我有预订架构:
let Booking = new Schema({
..., // others field of collection
experience: { type: Schema.Types.ObjectId, ref: 'Experience' },
...},{
collection: 'booking'
});
and Experienceschema:
和体验模式:
let Experience = new Schema({
...,
experienceType: {type: Schema.Types.ObjectId, ref: 'ExperienceType'},
location: {type: Schema.Types.ObjectId, ref: 'Location'},
...} // others field of collection
,{
collection: 'experience'
});
get ExperienceType and Locationof Experiencewhen you find Booking:
找到Booking时获取ExperienceType 和 Locationof Experience:
Booking.findOne({_id: req.params.id})
.populate({path: 'experience',
populate: [{path: 'experienceType', select: 'name'}, {path: 'location', select: 'name'}],
})
.exec((err, booking) => {
if(err){
console.log(err);
}
else {
res.json(booking);
}
});