猫鼬:人口密集(人口稠密)

f1n*_*1nn 59 populate mongoose mongodb

我有Category模特:

Category:
    ...
    articles: [{type:ObjectId, ref:'Article'}]
Run Code Online (Sandbox Code Playgroud)

文章模型包含ref Account model.

Article:
    ...
    account: {type:ObjectId, ref:'Account'}
Run Code Online (Sandbox Code Playgroud)

因此,填充的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' }
Run Code Online (Sandbox Code Playgroud)

问题是:如何填充填充字段的子字段(帐户)([articles])?我现在就是这样做的:

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
Run Code Online (Sandbox Code Playgroud)

我知道这里讨论过:Mongoose:填充一个填充的字段,但没有找到真正的解决方案

tec*_*ura 89

首先,更新mongoose 3到4然后使用最简单的方法在猫鼬中进行深度填充,如下所示:

假设您有具有userId作为ref Id的Blog模式,然后在User中您有一些评论作为模式审核的参考ID.所以基本上,你有三个架构:1.博客2.用户3.审查

而且,您必须从博客查询,哪个用户拥有此博客和用户评论.因此,您可以将结果查询为:

BlogModel
  .find({})
  .populate({
    path : 'userId',
    populate : {
      path : 'reviewId'
    }
  })
  .exec(function (err, res) {

  })
Run Code Online (Sandbox Code Playgroud)

  • 以防万一有人想知道是否要填充多个路径,您可以传入对象数组,如下所示: .populate([ { path: 'path_1', populate: { path: 'field_1' } }, { path: 'path_2 ', 填充: [{ 路径: 'field_1' }, { 路径: 'field_2' }] } ]).exec()。另请注意,在数组中给出简单字符串将无法像通常那样工作。请改用 { path: 'field' } 结构。 (6认同)
  • 这应该是正确的答案.谢谢@techyaura (5认同)
  • 如果我已经阅读了你的答案,并且没有浪费我一小时的时间在上面的答案! (3认同)
  • 感谢您显示查询的结构,而不仅仅是链接到文档。很棒! (3认同)
  • 当您想要填充两个字段时,您将如何填充第二级?当我使用 select: 时,它只为我返回最后一个字段,因为我只想返回第二级文档中的特定字段 (2认同)

小智 33

填充多个级别

假设您有一个跟踪用户朋友的用户架构.

var userSchema = new Schema({
  name: String,
  friends: [{ type: ObjectId, ref: 'User' }]
});
Run Code Online (Sandbox Code Playgroud)

Populate可以让你获得用户朋友的列表,但是如果你还想要用户的朋友朋友呢?指定populate选项以告诉mongoose填充所有用户朋友的friends数组:

User.findOne({ name: 'Val' }).populate({
    path: 'friends',
    // Get friends of friends - populate the 'friends' array for every friend
    populate: { path: 'friends' }
});
Run Code Online (Sandbox Code Playgroud)

参考:http://mongoosejs.com/docs/populate.html#deep-populate


Des*_*ova 21

Mongoose现在有了一种Model.populate深层关联的新方法:

https://github.com/LearnBoost/mongoose/issues/1377#issuecomment-15911192


Buu*_*yen 18

这可能有点太晚了,但我编写了一个Mongoose插件来执行任意嵌套级别的深度填充.注册此插件后,您只需一行即可填充类别的文章和帐户:

Category.deepPopulate(categories, 'articles.account', cb)
Run Code Online (Sandbox Code Playgroud)

您还可以指定填充选项来控制之类的东西limit,select...各填充路径.查看插件文档以获取更多信息.


cho*_*ovy 9

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);
    });
});
Run Code Online (Sandbox Code Playgroud)


Rav*_*ngh 8

或者您可以将 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) );
Run Code Online (Sandbox Code Playgroud)


小智 7

这个概念很深。这里Calendar、Subscription、User、Apartment是不同级别的mongoose 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)
                            }
                   });
Run Code Online (Sandbox Code Playgroud)


Kev*_*ang 5

很抱歉让您的泡沫破灭,但对此没有直接支持的解决方案。至于Github 问题#601,看起来很严峻。根据3.6 发行说明,开发人员似乎承认该问题对手动递归/深度填充感到满意。

因此,从发行说明来看,推荐的方法是在回调中嵌套填充的调用,因此在您的exec()函数中,categories.populate在发送响应之前使用进一步填充。