Mongoose填充子子文档

iam*_*esy 20 javascript mongoose mongodb node.js

我在MongoDB中有这个设置

项目:

title: String
comments: [] // of objectId's
Run Code Online (Sandbox Code Playgroud)

评论:

user: ObjectId()
item: ObjectId()
comment: String
Run Code Online (Sandbox Code Playgroud)

这是我的Mongoose架构:

itemSchema = mongoose.Schema({
    title: String,
    comments: [{ type: Schema.Types.ObjectId, ref: 'comments' }],
});

Item = mongoose.model('items', itemSchema);

commentSchema = mongoose.Schema({
    comment: String,
    user: { type: Schema.Types.ObjectId, ref: 'users' },
});

Comment = mongoose.model('comments', commentSchema);
Run Code Online (Sandbox Code Playgroud)

这是我得到我的项目和评论的地方:

Item.find({}).populate('comments').exec(function(err, data){
    if (err) return handleError(err);
    res.json(data);
});
Run Code Online (Sandbox Code Playgroud)

如何使用相应的用户填充注释数组?由于每条评论都有一个用户ObjectId()?

Ant*_*nka 83

还有一种方法(更容易):

Item
  .find({})
  .populate({
	path:     'comments',			
	populate: { path:  'user',
		    model: 'users' }
  })
  .exec(function(err, data){
    if (err) return handleError(err);
    res.json(data);
});
Run Code Online (Sandbox Code Playgroud)

  • 感谢您的回答。您的回答很好。 (3认同)
  • 顺便说一下,不需要第一个填充 (2认同)

Nei*_*unn 23

作为调用结果对象填充的完整示例:

Item.find({}).populate("comments").exec(function(err,data) {
    if (err) return handleError(err);

    async.forEach(data,function(item,callback) {
        User.populate(item.comments,{ "path": "user" },function(err,output) {
            if (err) throw err; // or do something

            callback();
        });
    }, function(err) {
        res.json(data);
    });

});
Run Code Online (Sandbox Code Playgroud)

该呼叫.populate()在从模型调用的形式它可以是一个文档或数组作为它的第一个参数.因此,您遍历每个项目的返回结果,并在每个"comments"数组上以这种方式调用填充."path"告诉函数它匹配的是什么.

这是使用forEach的"async"版本完成的,因此它是非阻塞的,但通常在所有操作之后,响应中的所有项目不仅填充了注释,而且注释本身具有相关的"用户"详细信息.


ste*_*red 12

更简单

Item
  .find({})
  .populate({
    path: 'comments.user',
    model: 'users' }
  })
  .exec(function(err, data){
    if (err) return handleError(err);
    res.json(data);
});
Run Code Online (Sandbox Code Playgroud)


小智 10

我用这个:

.populate({
            path: 'pathName',
            populate: [
                {
                    path: 'FirstSubPathName',
                    model: 'CorrespondingModel',
                },
                {
                    path: 'OtherSubPathName',
                    model: 'CorrespondingModel',
                },
                {
                    path: 'AnotherSubPathName',
                    model: 'CorrespondingModel',
                },
            ]
        });
Run Code Online (Sandbox Code Playgroud)

这是我发现的更简单的方法。我希望能有所帮助。:)


jac*_*son 7

要添加一个人们可能想要用来从子文档中仅选择特定字段的最终方法,您可以使用以下"select"语法:

  Model.findOne({ _id: 'example' })
    .populate({ 
      path: "comments", // 1st level subdoc (get comments)
      populate: { // 2nd level subdoc (get users in comments)
        path: "user",
        select: 'avatar name _id'// space separated (selected fields only)
      }
    })
    .exec((err, res) => { 
        // etc
     });
Run Code Online (Sandbox Code Playgroud)


Yas*_*jha 5

填充子子文档并从多个模式填充

ProjectMetadata.findOne({id:req.params.prjId})
.populate({
    path:'tasks',
    model:'task_metadata',
    populate:{
        path:'assigned_to',
        model:'users',
        select:'name employee_id -_id' // to select fields and remove _id field

    }
})
.populate({
    path:'client',
    model:'client'
})
.populate({
    path:'prjct_mgr',
    model:'users'
})
.populate({
    path:'acc_exec',
    model:'users'
})
.populate({
    path:'prj_type',
    model:'project_type'
}).then ( // .. your thing
Run Code Online (Sandbox Code Playgroud)

或者您可以按照以下方式进行..

   ProjectMetadata.findOne({id:req.params.prjId})
    .populate(
        [{
        path:'tasks',
        model:TaskMetadata,
        populate:[{
            path:'assigned_to',
            model:User,
            select:'name employee_id'
        },
        {
            path:'priority',
            model:Priority,
            select:'id title'
        }],
        select:"task_name id code assign_to stage priority_id"
    },
    {
        path:'client',
        model:Client,
        select:"client_name"
    },
    {
        path:'prjct_mgr',
        model:User,
        select:"name"
    },
    {
        path:'acc_exec',
        model:User,
        select:'name employee_id'
    },
    {
        path:'poc',
        model:User,
        select:'name employee_id'
    },
    {
        path:'prj_type',
        model:ProjectType,
        select:"type -_id"
    }

])
Run Code Online (Sandbox Code Playgroud)

当我必须获得同一父级的多个子子文档时,我发现第二种方法(使用数组)更有用。