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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 13:25:13  来源:igfitidea点击:

Mongoose: deep population (populate a populated field)

mongodbmongoosepopulate

提问by f1nn

I have Categorymodel:

我有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 articlesCategory model will be:

因此,使用填充的articlesCategory 模型将是:

{ //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.populatefor 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

参考: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.populateto 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 orders and include each orderDetail.

以下示例受到@codephobia 提出的问题的启发,并填充了许多关系的两个级别。首先获取 a user,填充其相关orders数组并包含每个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.8but should work in 3.6.x.

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